我正在尝试创建一种体验,用户可以将自定义光标移动到图像上并更改该自定义光标内的像素。
在这种情况mousemove
下,我尝试重新创建此自定义光标路径并使用isPointInPath来确定自定义光标是否“超过”主画布上下文中的给定点。
该代码确实改变了主画布中的一些像素。但是,下面列出了以下意外行为:
- 移动光标会改变主画布中多个区域的像素
- 主画布的 x 和 y 坐标(源自 imageData)不正确
(见下图)
为什么会这样?如何更改代码以使自定义光标(又名圆形)仅更改与主画布的该部分相对应的像素?
let image;
let imageData;
const cursorCanvas = document.createElement("canvas");
const cursorCanvasContext = cursorCanvas.getContext("2d");
cursorCanvas.width = 100;
cursorCanvas.height = 100;
drawCursor();
const imageCanvas = document.querySelector("canvas");
imageCanvas.width = window.innerWidth;
imageCanvas.height = window.innerHeight;
const imageCanvasContext = imageCanvas.getContext("2d");
document.querySelector("img").addEventListener("load", (event) => {
image = event.target;
image.crossOrigin = "Anonymous";
drawBackground();
imageData = imageCanvasContext.getImageData(
0,
0,
imageCanvas.width,
imageCanvas.height
);
});
window.addEventListener("mousemove", (event) => {
requestAnimationFrame(() => {
if (imageData) {
imageCanvasContext.beginPath();
imageCanvasContext.arc(
event.clientX,
event.clientY,
cursorCanvas.width / 2,
0,
2 * Math.PI
);
imageCanvasContext.closePath();
for (let i = 0; i < imageData.data.length; i += 4) {
const y = Math.floor(i / imageData.width);
const x = i - y * imageData.width;
if (imageCanvasContext.isPointInPath(x, y)) {
imageData.data[i] = 40;
imageData.data[i + 1] = 40;
imageData.data[i + 2] = 40;
}
}
imageCanvasContext.putImageData(imageData, 0, 0);
}
imageCanvasContext.drawImage(
cursorCanvas,
event.clientX - cursorCanvas.width / 2,
event.clientY - cursorCanvas.height / 2
);
});
});
function drawBackground() {
imageCanvasContext.clearRect(
0,
0,
imageCanvas.width,
imageCanvas.height
);
if (image) {
const ratio =
window.innerWidth > window.innerHeight ?
window.innerWidth / window.innerHeight :
window.innerHeight / window.innerWidth;
imageCanvasContext.drawImage(
image,
0,
0,
image.width,
image.height,
0,
0,
ratio * imageCanvas.width,
ratio * imageCanvas.height
);
}
}
function drawCursor() {
cursorCanvasContext.beginPath();
cursorCanvasContext.arc(
cursorCanvas.width / 2,
cursorCanvas.width / 2,
cursorCanvas.width / 2,
0,
2 * Math.PI
);
cursorCanvasContext.stroke();
cursorCanvasContext.closePath();
}
html,
body {
width: 100vw;
height: 100vh;
overflow: hidden;
}
body {
font-family: sans-serif;
margin: 0;
}
img {
visibility: hidden;
position: absolute;
}
canvas {
cursor: none;
}
<img src="https://i.imgur.com/vzGhITt.jpeg" />
<canvas />