为什么 2d canvas 不能在不模糊的情况下缩放?

Why does 2d canvas not scale without blurring?

我正在尝试使用 2d canvas 构建一个超级简单的像素网格 (20x20)。 我想使用不同大小的属性和 CSS.

来扩大它 (*10)

我认为它应该这样工作,因为宽度和高度属性应该代表记录的网格像素。但是当我使用 CSS 缩放它时,像素以某种方式开始抗锯齿(?)而不是保持简单的像素(矩形)。将抗锯齿设置为 false,没有任何效果。

为什么 是这样,有没有办法解决这个问题,除了 CSS 之外不对其他所有内容应用比例? (我可以将一个像素设为 10 像素宽,但这破坏了简洁性)。

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);

您可以使用CSS/图像渲染风格,并将其设置为像素化。

More details -> https://developer.mozilla.org/en-US/docs/Web/CSS/image-rendering

例如

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);

canvas的宽度和高度属性在某种意义上是它的真实尺寸。 canvas 像素根据这些尺寸定位。 style.width 和 style.height 是用于在屏幕上显示 canvas 元素的尺寸。

所以最终结果是 canvas 被浏览器拉伸以满足那些样式属性。这会将 20x20 canvas 像素拉伸到 200*200 canvas 元素区域。

相反

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);

结论: canvasapi根据width和height属性计算每个像素的位置

然后浏览器会根据 style.width 和 style.height css 属性将其放大。

通过在 javascript 中缩放它。在屏幕上绘制之前将计算像素的位置。

将 canvas 的宽度和高度属性设置为所需的尺寸,以便浏览器在绘制后不会放大它。