我正在使用HTML5 Canvas绘制线条。通过在多个中间点上调用drawLine()来形成单行。例如:
(0,0) - > (10,10) - > (10,5) - > (20,12)
会在情节中显示为一行。
一行的所有(x,y)坐标都存储在一个数组中。
我想让用户在点击它时选择一条线。在HTML5 Canvas中执行此操作变得很困难,因为该行不是由对象表示的。我唯一的选择是首先找到最接近mousedown事件的(x,y)的任何一行的(x,y)坐标。一旦我检测到用户选择了哪一行,我就需要用粗体颜色重新绘制线条或在其周围涂上半透明的颜色。但是,我假设这会耗费太多时间,因为它涉及遍历所有行的所有(x,y)坐标。
我正在寻找可以帮助我以更节省时间的方式实现上述目标的方法。我应该考虑在HTML5中使用SVG吗?
任何建议都将不胜感激。
答案 0 :(得分:6)
在HTML5画布中执行此操作的最简单方法是拍摄画布的图像数据的快照,并在鼠标移动期间查看鼠标下像素的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;
});
答案 1 :(得分:4)
我认为你在SVG中发现这一点要容易得多。每一行都是<polyline>
,您可以添加一个onclick处理程序来执行您想要的操作。例如......
<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>
答案 2 :(得分:1)
在画布上执行此操作的唯一方法是检测像素颜色并遵循路径或将路径保存为对象并检测该路径上的单击。