为什么在 canvas 上画得离光标很远?

Why does it draw far away from the cursor on a canvas?

我先给出我的代码:

document.documentElement.style.backgroundImage='url(\'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><rect width="20" height="20" style="fill-opacity:0;stroke-width:1;stroke:rgb(0,0,255)"/></svg>\')';
var c=document.getElementById("paper").getContext("2d");
c.fillStyle="#000000";
document.documentElement.onmousemove=function(e){
    if((e.buttons||e.which)===1){
        var x=e.pageX,y=e.pageY;
        c.fillRect(x,y,1,1);
    }
};
html{width:100vw;height:100vh;overflow:hidden;background-repeat:repeat;cursor:crosshair}
body{margin:0}
#paper{position:absolute;left:0;top:0;width:100vw;height:100vh;z-index:1}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Graph Paper</title>
    </head>
    <body>
        <canvas id="paper"></canvas>
    </body>
</html>

我正在尝试制作一张可以用光标在上面绘图的虚拟方格纸。问题是,如果你 运行 它并(使用你的鼠标)画东西,你会注意到它画的地方实际上并不是你所在的地方 - 当你离得越远它离你越远(0,0).

我的代码有点简单,所以我不知道为什么要这样做。例如,如果你从中间开始,向 (0,0) 移动,你会看到它从你身后开始,但与你同时到达。如果您从中间开始向右下角移动,当您到达时它会比您远。

我怀疑这与 canvas 位置错误或 e.pageXe.pageY 在某些方面不正确有关。

为什么这个看似简单的代码不起作用?

用 css 拉伸 canvas 不会改变 canvas 的基本分辨率,而只是获取生成的图像并对其进行缩放(通常也很差)。

如果 canvas 例如由于 css,你的像素数被拉伸了两倍:canvas 将它向内渲染与你的鼠标坐标一样多的像素,但结果随后被拉伸 css之后。

您可以通过一些计算来弥补这一点,但通常最好使 canvas 本身成为正确的大小:

const canvas = document.getElementById("paper");
const ctx = canvas.getContext("2d");
document.documentElement.style.backgroundImage = 'url(\'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20"><rect width="20" height="20" style="fill-opacity:0;stroke-width:1;stroke:rgb(0,0,255)"/></svg>\')';
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.fillStyle = "#000000";
document.documentElement.onmousemove=function(e){
    if ((e.buttons || e.which) === 1) {
        const x = e.pageX, y = e.pageY;
        ctx.fillRect(x, y, 1, 1);
    }
};
html {
  width: 100vw;
  height: 100vh;
  overflow: hidden;
  background-repeat: repeat;
  cursor: crosshair
}
body { margin: 0 }
#paper {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 1
}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8"/>
        <title>Graph Paper</title>
    </head>
    <body>
        <canvas id="paper"></canvas>
    </body>
</html>

请注意,通过这种方式,您无法免费调整大小。如果要调整 window 的大小,您需要再次更改 canvas,从我在这里省略的代码中。