如何选择在HTML5画布上绘制的线条?

10

我正在使用HTML5 Canvas来绘制线条。一个单独的线条是由在多个中间点上调用drawLine()函数形成的。例如:

(0, 0) -> (10, 10) -> (10, 5) -> (20, 12)

将在图中显示为一条线。

所有线条的(x, y)坐标都存储在一个数组中。

我想提供给用户选择线条的能力,让他们点击它时可以选择。在HTML5 Canvas中实现这一点变得困难,因为线条不是以对象的形式表示的。我唯一剩下的选择是首先找到任何一条线最接近按下鼠标事件的(x, y)坐标。一旦我检测到用户选择了哪条线,那么我就需要用粗体颜色重新绘制该线或在其周围放置半透明的颜色。但是,我认为这样做会太费时间,因为它涉及到循环遍历所有线条的所有(x, y)坐标。

我正在寻找可以帮助我以更高效的方式实现上述目标的方法。我应该考虑在HTML5中使用SVG吗?

任何建议都将不胜感激。


参考以下链接:https://dev59.com/K4Xca4cB1Zd3GeqPN9ON#27336242那里的答案更加清晰。 - Riyafa Abdul Hameed
3个回答

11

在HTML5画布中最简单的方法是对画布的图像数据进行快照,在mousemove事件期间查看鼠标下方像素处的alpha颜色。

我在我的网站上放了一个工作示例:
http://phrogz.net/tmp/canvas_detect_mouseover.html

以下是我编写的核心代码。将上下文和一个函数传递给它,它将使用像素下面的RGBA组件调用您的函数。

function pixelOnMouseOver(ctx,callback){
  var canvas = ctx.canvas;
  var w = canvas.width, h=canvas.height;
  var data = ctx.getImageData(0,0,w,h).data;
  canvas.addEventListener('mousemove',function(e){
    var idx = (e.offsetY*w + e.offsetX)*4;
    var parts = Array.prototype.slice.call(data,idx,idx+4);
    callback.apply(ctx,parts);
  },false);
}

以下是在测试页面上如何使用它:

var wasOver;
pixelOnMouseOver(ctx,function(r,g,b,a){
  var isOver = a > 10; // arbitrary threshold
  if (isOver != wasOver){
    can.style.backgroundColor = isOver ? '#ff6' : '';
    wasOver = isOver;
  }
  out.innerHTML = "r:"+r+", g:"+g+", b:"+b+", a:"+a;
});

非常酷 - 但请注意,如果鼠标移动得太快,它不总是准确地报告它是否在画布上或离开了画布。 - ashleedawg

6

我认为你可以使用SVG更容易实现这个功能。每一条线都可以用<polyline>来表示,并且你可以添加一个点击事件处理程序来实现你想要的功能。例如...

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
    <polyline points="20,20 40,25 60,40 80,120 120,140 200,180" 
              style="fill:none;stroke:black;stroke-width:5"
              onclick="this.style.stroke='red'" />
</svg>

感谢您的回复,Robert。如果我事先知道要绘制的线条数量,SVG方法将起作用。如果我让用户通过某些UI按钮动态创建新行,那么这种方法是否需要每次创建一条线时修改实际的SVG文件? - kkonweb
2
没错,但这不难,只需要使用document.createElementNS("http://www.w3.org/2000/svg", "polyline")来创建新的折线。 - Robert Longson

1

在画布上实现此功能的唯一方法是检测像素颜色并跟随路径,或将路径保存为对象并检测该路径上的点击。


请注意,使用填充路径时,您还可以使用ctx.isPointInPath(x,y) - Phrogz
没错,这就是为什么我首先添加了自己的答案,展示了描边线的工作解决方案。 - Phrogz

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