Since you don't seem to accept the duplicate, here is an explanation just for you :
Canvas has its own coordinate matrix
This implies that the x
and y
values you do use in the drawing methods will be dependent on this matrix, not the one of your view-page.
The following example will show you that for two exact same canvases, the result will look different on screen because of the CSS you applied on them :
var ctx = normal.getContext('2d'),
ctx2 = CSS_stretched.getContext('2d');
ctx.textAlign = ctx2.textAlign = 'center';
ctx.textBaseline = ctx2.textBaseline ='bottom';
for(var i=0; i<26; i++){
ctx.fillRect(i*20, 0, 1, 10);
ctx2.fillRect(i*20, 0, 1, 10);
ctx.fillText(i*20, i*20, 25);
ctx2.fillText(i*20, i*20, 25);
}
#CSS_stretched{width : 50%;}
canvas{border: 1px solid black;}
p,canvas{display: block}
<p>Unstretched canvas:</p>
<canvas id="normal" width="500" height ="25"></canvas>
<p>Stretched canvas :</p>
<canvas id="CSS_stretched" width="500" height ="25"></canvas>
This becomes a real pain when you try to use some functionnalities such as mouse coordinates to paint on your canvas, since the event coordinates are based on the page ones :
var ctx = canvas.getContext('2d');
canvas.onmousemove = function(e){
var x = e.clientX - this.offsetLeft;
var y = e.clientY - this.offsetTop;
ctx.clearRect(0,0,canvas.width, canvas.height)
ctx.fillRect(x-1, y-20, 2, 40)
ctx.fillRect(x-20, y-1, 40, 2)
}
stretch.onclick = function(){
canvas.className = canvas.className?'':'stretched';
}
canvas{border: 1px solid black;}
.stretched{width: 100%;}
<button id="stretch">toggle CSS stretching</button><br>
<canvas id="canvas" width="250" height="135" class="stretched"></canvas>
CSS stretching implies antialiasing algorithm
It also does provide an image-rendering
property, but I don't think it will do what you want...
When you tell the browser to render at a smaller scale, you are telling him that the pixels are smaller than a pixel. It then has to create false semi-transparent ones around the original pixel location. This will also create some artifacts and the impression of a crappy rendering.
You can already see this effect in the first snippet :
Note that even on non-scaled canvas, browsers already apply antialiasing, but crapped crap is just crappier.
So, now that I hope you've got the why "it bugs out while drawing", we can come to the solutions :
Don't use CSS to set your canvas size. Instead, set the canvas .width
and .height
properties.
That's the easiest and the only solution I can recommend.
Of course, in your own case it does imply other problems that you already encountered :
If you set the canvas size to the page's one, small screens will have cropped canvases.
One solution to this is to use a container, that will allow scroll-bars to appear only for the canvas.
You could also fix everyone's canvas to the smallest one, but if you're also targeting mobiles, then it will looks odd on larger screens.
Or, you will have to make all the calculations to convert the canvases coordinates to relative ones (strokes included) and if you do write it, I'd be pleased to see the code.
But this is a design problem that only you can answer.
