Home > Mobile >  Why does 2d canvas not scale without blurring?
Why does 2d canvas not scale without blurring?

Time:11-30

I am trying to build a super simple pixel grid (20x20) with a 2d canvas. And I would like to scale it up (*10) using different sizes for the attributes and the CSS.

I thought it should work that way, since the width and height attributes should represent the pixels of the grid as documented. But when I scale it using CSS, the pixels start antialiasing(?) somehow instead of staying simple pixels (rectangles). Setting antialias to false, did not have any effect.

Why is that and is there a way to solve it, without applying the scale to everything else but the CSS? (I could make one pixel 10 pixels wide, but that ruins the simplicity).

const element = document.createElement('canvas');
const canvas = element.getContext("2d", {antialias: false});

const size = 20;
const scale = 10;

element.width = size;
element.height = size;
element.style.width = size * scale   'px';
element.style.height = size * scale   'px';

[{x:10, y: 4}, 
 {x:10, y: 6}, 
 {x:10, y: 12}, 
 {x:10, y: 13}]
.forEach(({x, y}) => canvas.fillRect(x, y, 1, 1));

document.body.appendChild(element);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You can use the CSS / Style of image-rendering, and set it to pixelated.

eg.

const element = document.createElement('canvas');
const canvas = element.getContext("2d");
element.style.imageRendering = 'pixelated';


const size = 20;
const scale = 10;

element.width = size;
element.height = size;
element.style.width = size * scale   'px';
element.style.height = size * scale   'px';

[{x:10, y: 4}, 
 {x:10, y: 6}, 
 {x:10, y: 12}, 
 {x:10, y: 13}]
.forEach(({x, y}) => canvas.fillRect(x, y, 1, 1));

document.body.appendChild(element);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

the width and height attribute of the canvas is its true dimensions in a sense. The canvas pixels are positioned according to those dimensions. style.width and style.height are the dimensions used to display the canvas element on screen.

So the final result is a canvas stretched by the browser to meet those style attributes. This will stretch the 20x20 canvas of pixels to a 200*200 canvas element area.

Instead

<head>
<title>stretched canvas</title>
</head>
<body>
</body>
<script>
const element = document.createElement('canvas');
const canvas = element.getContext("2d", {antialias: false});

const size = 20;
const scale = 10;

element.width = size * scale;// scale the true dimensions of the canvas.(i.e the canvas's coordinate system)
element.height = size * scale;
element.style.width = size * scale   'px';
element.style.height = size * scale   'px';
canvas.scale(scale,scale);//now when determining the coordinates, all the dimensions will be pre scaled and so each pixel that will be drawn will be calculated before being rendered instead of being stretched by the browser after 
[{x:10, y: 4}, 
 {x:10, y: 6}, 
 {x:10, y: 12}, 
 {x:10, y: 13}]
.forEach(({x, y}) => canvas.fillRect(x, y, 1, 1));

document.body.appendChild(element);
</script>
</html>```

Conclusion:
The canvas api calculates the positions of each pixel based on the width and height attributes.

The browser then scales it up according to the style.width and style.height css properties. 

By scaling it in javascript. The positions of the pixels will be calculated before being drawing onscreen. 

Set the width and height attributes of the canvas to the wanted dimensions so that the browser won't scale it up after being drawn.
  • Related