2

I'll first give my code:

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>

I'm trying to make a virtual graph paper you can draw on with the cursor. The problem is that if you run it and (using your mouse) draw something, you will notice that the place it draws isn't actually where you're at - it's farther away from you as you get farther away from (0,0).

My code is a bit simple so I have no idea on why it is doing this. For example, if you start in the middle, and move towards (0,0), you will see it starts behind you but reaches at the same time as you. And if you start in the middle and go towards the bottom right, it will get much farther than you by the time you reach.

I suspect this has something to do with either the canvas being mispositioned or e.pageX and e.pageY to be incorrect in some way.

Why is this seemingly simple code not working?

Lakshya Raj
  • 1,669
  • 3
  • 10
  • 34
  • Stretching the canvas with css probably causes this – ASDFGerte Apr 16 '21 at 15:41
  • @ASDFGerte: Hmmm... when testing it seems to be true. But then how do I get the canvas to stretch across the whole screen? – Lakshya Raj Apr 16 '21 at 15:43
  • You could either compensate for the stretching, with some small math, or modify the canvas' `width` and `height` according to the size of your viewport. PS: stretching canvas with css means it will upscale your image, the canvas still renders at low resolution, but the resulting image is then stretched. – ASDFGerte Apr 16 '21 at 15:44
  • @ASDFGerte: So you suggest JavaScript should set the width and height? OK. Add an answer to the question and I will accept it. Thanks for your help! – Lakshya Raj Apr 16 '21 at 15:45

1 Answers1

1

Stretching a canvas with css does not change the underlying resolution of the canvas, but simply takes the resulting image, and scales it (usually rather poorly as well).

If the canvas is e.g. stretched by a factor of two due to css, your pixel counting is accordingly off by that factor: the canvas renders it inwards as many pixels as your mouse coordinates, but the result is then stretched by css afterwards.

You could compensate for this by some calculations, but it's often better to make the canvas itself the correct size:

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>

Note, that this way, you don't get resizing for free. Should the window be resized, you'd need to change the canvas again, from code, which i have omitted here.

ASDFGerte
  • 4,695
  • 6
  • 16
  • 33
  • Thanks for all of your help! I knew of this CSS resize issue but it is hard to remember when the problems arrive :) – Lakshya Raj Apr 16 '21 at 16:11