html5-canvas - 针对文本形状的 HitTest

标签 html5-canvas raphael paperjs

我想知道给定的点是在文本形状的内部还是外部。正如您在下面提供的示例中注意到的那样,只要点位于 TextItem 的边界内,hitTest 就会返回 true,而且不仅是当点在角色本身内部时。 (当您将鼠标指针放在 # 的中间时,您可以最好地体验这种行为)

Sample: Hit-testing against TextItem

我还尝试根据路径绘制角色(正如 Raphaël 在他们的 font samples 中所做的那样)以使用路径本身进行 HitTest ,但偶然发现了一些非常奇怪的行为,其中(一些)字符未正确绘制。 (如果您将路径定义复制到矢量图像软件中,如 Inkscape,文本形状将被正确绘制)

Sample: Drawing text as path

找出给定点是在文本形状内部还是外部的最有希望的方法是什么?

最佳答案

您可以通过发送文本鼠标下方的像素是否透明来对文本形状(或任何其他数学上不规则的形状)进行 HitTest 。

您可以使用以下方法获取整个 Canvas 的像素数组:

var data=context.getImageData(0,0,canvas.width,canvas.height).data;

然后您可以像这样获取鼠标下方像素的不透明度 (alpha) 值:

var pixelIsTransparent = data[(mouseY*canvas.width+mouseX)*4+3]==0

如果像素不透明,则说明您位于文本形状之上。

如果您在 Canvas 上有其他非文本绘图,那么这些非文本绘图可能会为您的 HitTest 提供误报。一种解决方法是使用仅包含文本形状的第二个内存 Canvas ,然后对第二个 Canvas 上的像素进行 HitTest 。

这是示例代码和演示:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var $canvas=$("#canvas");
var canvasOffset=$canvas.offset();
var offsetX=canvasOffset.left;
var offsetY=canvasOffset.top;

ctx.strokeStyle='gray';
ctx.font='300px verdana';
var wasHit=false;
var isHit=false;

draw();

var data=ctx.getImageData(0,0,canvas.width,canvas.height).data;

$("#canvas").mousemove(function(e){handleMouseMove(e);});


function draw(){
  ctx.fillStyle=(isHit)?'green':'lightgray';
  ctx.fillText("M",25,250);
  ctx.strokeText("M",25,250);
}


function handleMouseMove(e){
  e.preventDefault();
  e.stopPropagation();

  mouseX=parseInt(e.clientX-offsetX);
  mouseY=parseInt(e.clientY-offsetY);

  isHit=(data[(mouseY*cw+mouseX)*4+3]>10)
  if(!isHit==wasHit){
    draw();
    wasHit=isHit;
  }
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<p>Hit test: Move mouse over letter</p>
<canvas id="canvas" width=300 height=300></canvas>

关于html5-canvas - 针对文本形状的 HitTest ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26375877/

相关文章:

javascript - paper.js 代码未运行

javascript - 如何在 paper.js 中沿着贝塞尔曲线路径对对象进行动画处理?

angular - 如何创建响应调整大小的基于 Angular 2 Canvas 的组件?

JavaScript 碰撞检测错误

javascript - 如何在 SVG/raphael 中的贝塞尔曲线末端绘制箭头?

css - Raphael.js 的彩色图像到灰度图像在 I.E. 中不起作用9

javascript - paper.js - 使用闭合路径实现更平滑的边缘

javascript - 如何判断浏览器是否为HTML5 Canvas提供硬件加速

javascript - 如何使用 HTML5 Canvas 为同一行中的不同单词着色?

javascript - 响应式或流畅布局的跨浏览器 SVG?