canvas使用更多ctx元素
我的任务是创建两个画布(大和小)。在大一颗中创建 5 颗不同颜色的星星。
任务:通过单击星星,将小画布的颜色更改为星星的颜色。现在的问题是 addEventListener
仅适用于最后一个元素。有什么想法吗?
.html
模板:
<canvas style="background-color:rgb(255, 255, 255); border: 1px solid black" id='big'>Обновите браузер</canvas>
<canvas style="background-color:rgb(255, 255, 255); border: 1px solid black" id='small'>Обновите браузер</canvas>
.js
脚本:
const big = document.getElementById("big");
const small = document.getElementById("small");
big.height = 600;
big.width = 600;
small.height = 600;
small.width = 50;
function createStar(moveToX, moveToY, lineToX1, lineToY1, lineToX2, lineToY2, lineToX3, lineToY3, lineToX4, lineToY4, color) {
ctx = big.getContext('2d');
ctx.beginPath();
ctx.moveTo(moveToX, moveToY);
ctx.lineTo(lineToX1, lineToY1);
ctx.lineTo(lineToX2, lineToY2);
ctx.lineTo(lineToX3, lineToY3);
ctx.lineTo(lineToX4, lineToY4);
ctx.closePath();
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.fill();
ctx.stroke();
};
const red = new createStar(20, 60, 100, 60, 35, 110, 60, 25, 85, 110, 'red');
const blue = new createStar(120, 60, 200, 60, 135, 110, 160, 25, 185, 110, 'blue');
const green = new createStar(120, 160, 200, 160, 135, 210, 160, 125, 185, 210, 'green');
const black = new createStar(220, 460, 400, 460, 235, 560, 300, 400, 385, 560, 'black');
const yellow = new createStar(220, 260, 300, 260, 235, 310, 260, 225, 285, 310, 'yellow');
big.addEventListener('click', function(e){
if(ctx.isPointInPath(e.offsetX, e.offsetY)) {
small.style.backgroundColor = 'red';
} else {
small.style.backgroundColor = 'white';
}
});
My task is to create two canvases (big and small). In big one create 5 stars of different colors.
Task: by clicking on the star, change the color of the small canvas to the color of the star. Now the problem is that addEventListener
only works on the last element. Any ideas?
.html
template:
<canvas style="background-color:rgb(255, 255, 255); border: 1px solid black" id='big'>Обновите браузер</canvas>
<canvas style="background-color:rgb(255, 255, 255); border: 1px solid black" id='small'>Обновите браузер</canvas>
.js
script:
const big = document.getElementById("big");
const small = document.getElementById("small");
big.height = 600;
big.width = 600;
small.height = 600;
small.width = 50;
function createStar(moveToX, moveToY, lineToX1, lineToY1, lineToX2, lineToY2, lineToX3, lineToY3, lineToX4, lineToY4, color) {
ctx = big.getContext('2d');
ctx.beginPath();
ctx.moveTo(moveToX, moveToY);
ctx.lineTo(lineToX1, lineToY1);
ctx.lineTo(lineToX2, lineToY2);
ctx.lineTo(lineToX3, lineToY3);
ctx.lineTo(lineToX4, lineToY4);
ctx.closePath();
ctx.strokeStyle = color;
ctx.fillStyle = color;
ctx.fill();
ctx.stroke();
};
const red = new createStar(20, 60, 100, 60, 35, 110, 60, 25, 85, 110, 'red');
const blue = new createStar(120, 60, 200, 60, 135, 110, 160, 25, 185, 110, 'blue');
const green = new createStar(120, 160, 200, 160, 135, 210, 160, 125, 185, 210, 'green');
const black = new createStar(220, 460, 400, 460, 235, 560, 300, 400, 385, 560, 'black');
const yellow = new createStar(220, 260, 300, 260, 235, 310, 260, 225, 285, 310, 'yellow');
big.addEventListener('click', function(e){
if(ctx.isPointInPath(e.offsetX, e.offsetY)) {
small.style.backgroundColor = 'red';
} else {
small.style.backgroundColor = 'white';
}
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
context.isPointInPath(x, y)
将检查坐标
x
和y
处的点是否位于上下文中正在跟踪的当前子路径内。每次调用 ctx.beginPath() 时,该子路径都会被清除。
要解决此问题,您必须重新追踪整个星星列表,并逐一检查该点是否落在其中。
不过,您还可以使用 Path2D 接口 。
该接口允许将此类子路径保存为自己的对象,并且可以由上下文使用,而不是内部上下文的路径,例如 ctx.fill(path) 、 ctx.lines(路径),
ctx.clip(路径)
,ctx.scrollPathIntoView(路径)
,ctx.drawFocusIfNeeded(路径,元素)
, 和您可能已经猜到了,ctx.isPointInPath(path, x, y)
或ctx.isPointInStroke(path, x, y)
。因此,您可以重写代码,以便每颗星星都存储在其自己的 Path2D 实例中,将所有这些实例存储在一个数组中,然后遍历该数组以检查其中是否有任何一个被该点击中:
context.isPointInPath(x, y)
will check if the point at coordsx
andy
is inside the current sub-path that's being traced in the context.Every time you call
ctx.beginPath()
, this sub-path is cleared.To workaround that you would have to retrace the whole list of stars and check one by one if the point falls in there.
However, there is also a Path2D interface that you can use.
This interface allows to hold such sub-path as their own object, and can be used by the context instead of the internal context's path by e.g
ctx.fill(path)
,ctx.stroke(path)
,ctx.clip(path)
,ctx.scrollPathIntoView(path)
,ctx.drawFocusIfNeeded(path, element)
, and you probably guessed it,ctx.isPointInPath(path, x, y)
, orctx.isPointInStroke(path, x, y)
.So you can rewrite your code so that each star is stored in its own Path2D instance, store all these instances in an Array and then traverse that Array to check if any of these was hit by the point: