为啥 2d 画布在不模糊的情况下无法缩放?

Posted

技术标签:

【中文标题】为啥 2d 画布在不模糊的情况下无法缩放?【英文标题】:Why does 2d canvas not scale without blurring?为什么 2d 画布在不模糊的情况下无法缩放? 【发布时间】:2022-01-07 02:02:18 【问题描述】:

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

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

为什么是这样的,有没有办法解决它,而不是将比例应用于除 CSS 之外的所有其他东西? (我可以将 1 个像素设为 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);

【问题讨论】:

【参考方案1】:

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

更多细节-> 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);

【讨论】:

谢谢!迷人的,完美的矩形,无论我放大多少!我没想到,CSS 与画布的耦合如此紧密。您是否知道这是否详细记录在某处? @Basti 更多细节在这里 -> developer.mozilla.org/en-US/docs/Web/CSS/image-rendering【参考方案2】:

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

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

相反

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

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

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

通过在 javascript 中缩放它。像素的位置会在绘制到屏幕之前计算出来。

将画布的宽度和高度属性设置为想要的尺寸,这样浏览器在绘制后就不会放大。

【讨论】:

建议编辑的人。我看不到它,因为我需要 2k 代表。 我嵌入了截取的代码,所以可以原地执行,估计很快就会被社区接受。感谢您的回答!好的,有效的解决方案!

以上是关于为啥 2d 画布在不模糊的情况下无法缩放?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 webkit 浏览器下缩放 SVG 会变得模糊?

HTML5 Canvas - 在不翻译上下文的情况下相对于对象的中心进行缩放

画布上的模糊 svg

如何在不实际缩放的情况下更改视图缩放值?

如何在不缩放图像子视图的情况下缩放图像?迅速的ios

如何在不更改用户设置的缩放比例的情况下更新地图标记?