HTML5画布上的贝塞尔路径形状点击检测

8

我有一个带有一些不规则形状图形的画布,当有人点击特定的图形时,我想要得到反馈?

我已经到处寻找解决方案,但只找到了矩形的解决方案。

我认为这可能与isPointInPath()有关,但我还没有找到如何使用它的简明说明。

欢迎任何帮助。

3个回答

13

我写了一个教程,使用第二个不可见的画布来进行对象选择/命中测试。将所有形状逐个绘制在第二个画布上,直到鼠标位置出现黑色像素为止,然后就找到了你要的对象!

以下是我写的有关使用canvas选择对象的一些内容:

  // gctx is ghost context, made from the second canvas
  // clear(gctx)

  // ...

  // run through all the boxes
  var l = boxes.length;
  for (var i = l-1; i >= 0; i--) {
    // draw shape onto ghost context
    drawshape(gctx, boxes[i], 'black', 'black');

    // get image data at the mouse x,y pixel
    var imageData = gctx.getImageData(mx, my, 1, 1);
    var index = (mx + my * imageData.width) * 4;

    // if the mouse pixel exists, select and break
    if (imageData.data[3] > 0) {
      mySel = boxes[i];
      offsetx = mx - mySel.x;
      offsety = my - mySel.y;
      mySel.x = mx - offsetx;
      mySel.y = my - offsety;
      isDrag = true;
      canvas.onmousemove = myMove;
      invalidate();
      clear(gctx);
      return;
    }

  }

我的完整演示只使用矩形,但在后续版本中我将使用圆形/路径/文本。

如果您想查看演示和我的完整代码,请点击此处


我最终做了类似的事情,尽管我留在了相同的画布上,在重新绘制形状时没有进行任何笔画或填充。 - Brousselaine
@Simon Sarris 我使用了您的教程来制作这个:http://edumax.org.ro/extra/new/mindmap/(使用网格作为地图,右键单击以显示菜单)。我正在尝试通过使用您的方法使路径也可选择。我知道您即将发布有关此内容的教程,但是否有一种方式可以给我们一些基本步骤的提示?(特别是对于路径.contains()函数) - Vlad Otrocol
抱歉,我现在几乎所有的空闲时间都花在写书上了,可能要到年底才能回到我的网络教程系列。使路径可选择可以使用上下文的 isPointInPath 函数完成,但您必须保存制作每个路径所需的所有步骤,并在每次需要测试时加载上下文的当前路径。 - Simon Sarris

0

这可以通过使用Path2D来实现。

var div = document.getElementById("result");
var canvas = document.getElementById("canvas");

var ctx = canvas.getContext("2d");

var path1 = new Path2D();
path1.rect(10, 10, 100, 100);
path1.closePath();
ctx.stroke(path1);

var path2 = new Path2D();
path2.moveTo(220, 60);
path2.arc(170, 60, 50, 0, 2 * Math.PI);
path2.closePath();
ctx.stroke(path2);

var path3 = new Path2D("M230 10 h 80 v 80 h -80 Z");
ctx.fill(path3);
path3.closePath();

$('canvas').click( function(event) 
{
  div.innerHTML = "";
  
  var x = event.pageX;
  var y = event.pageY;

  if (ctx.isPointInPath(path1, x, y))
    div.innerHTML = "Path1 clicked";

  if (ctx.isPointInPath(path2, x, y))
    div.innerHTML = "Path2 clicked";
  
  if (ctx.isPointInPath(path3, x, y))
    div.innerHTML = "Path3 clicked";
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
  <canvas id="canvas"></canvas>
  <div id="result"></div>
</body>


0
你可以使用路径迭代器,将所有形状转换为近似的多边形。 然后使用“点在多边形内”算法来检查点是否在形状内。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接