使用isPointInPath
时,有没有办法利用drawImage
之类的内容?
示例:
drawImage
绘制顶部画布,isPointInPath
不起作用。arc
和isPointInPath
工作。**编辑**
我在一个画布上绘制一个圆圈,并使用isPointInPath
查看鼠标指针是否位于圆圈内(我的示例中为底部画布)。
我还使用drawImage
将底部画布“复制”到顶部画布。请注意,isPointInPath
不能在顶部画布上工作(很可能是由于我上面提到的原因)。有没有我可以使用的解决方案,适用于任何类型的路径(或位图)?
答案 0 :(得分:3)
画布上下文有一个称为当前路径的隐藏事物。 ctx.beginPath
,ctx.lineTo
等创建此路径。
当您调用ctx.stroke()
或ctx.fill()
画布笔划或填充该路径时。
即使在描边或填充之后,路径仍然存在于上下文中。
此路径是isPointInPath
测试的唯一事物。
如果你想测试你绘制的图像中是否有某个东西或者用ctx.fillRect()
绘制的矩形,那么使用内置方法是不可能的。
通常,您希望使用自己编写的is-point-in-rectangle函数(或从其他人那里获取)。
如果您正在寻找如何对图像进行像素完美(而不仅仅是图像矩形)点击检测图像,可以采用多种方法执行此处讨论:Pixel perfect 2D mouse picking with Canvas
答案 1 :(得分:1)
您可以尝试重新实现ctx.drawImage()
以始终在图像背后绘制一个框,如此(JSFiddle example):
ctx.customDrawImage = function(image, x, y){
this.drawImage(image, x, y);
this.rect(x, y, image.width, image.height);
}
var img1 = new Image();
img1.onload = function(){
var x = y = 0;
ctx.drawImage(img1, x, y);
console.log(ctx.isPointInPath(x + 1, y + 1));
x = 1.25 * img1.width;
ctx.customDrawImage(img1, x, y);
console.log(ctx.isPointInPath(x + 1, y + 1));
注意:您可能会出现副作用,例如图像上出现的矩形,或者如果您不小心,可能会从后面流血。
答案 2 :(得分:0)
对我来说,在移动画布后isPointInPath失败了。所以,我用过:
mouseClientX -= gCanvasElement.offsetLeft;
mouseclientY -= gCanvasElement.offsetTop;
答案 3 :(得分:0)
我还有更多挑战,因为我的canvas元素可以重新缩放。所以首先,当我绘制图形时,在我的情况下是弧,我将它们与名称一起保存在数组中并绘制它们:
if (this.coInit == false)
{
let co = new TempCO ();
co.name= sensor.Name;
co.path = new Path2D();
co.path.arc(c.X, c.Y, this.radius, 0, 2 * Math.PI);
this.coWithPath.push(co);
}
let coWP = this.coWithPath.find(c=>c.name == sensor.Name);
this.ctx.fillStyle = color;
this.ctx.fill(coWP.path);
然后在鼠标事件中,遍历所有项目,并检查click事件是否在路径中。但是我还需要根据调整后的画布重新调整鼠标坐标的大小:
getCursorPosition(event) {
const rect = this.ctx.canvas.getBoundingClientRect();
const x = ((event.clientX - rect.left ) / rect.width) * this.canvasWidth;
const y = ((event.clientY - rect.top) / rect.height) * this.canvasHeight;
this.coWithPath.forEach(c=>{
if (this.ctx.isPointInPath(c.path, x, y))
{
console.log("arc is hit", c);
//Switch light
}
});
}
因此,我得到了画布的当前大小,并将该点重新缩放为原始大小。现在可以了!
TempCO的外观如下:
export class TempCO
{
path : Path2D;
name : string;
}