奇怪 HTML 5 Canvas 抗锯齿
Weird HTML 5 Canvas Antialiasing
我一直在玩 canvas 元素并发现当我尝试绘制彼此相邻的 NxN 统一纯色单元格时,在某些 width/height 配置中,有模糊的白色 -他们之间的线条。
例如,这个 canvas 应该看起来是黑色的,但包含某种 网格 ,我猜想这是浏览器中错误的抗锯齿的结果。
可以这么说,这个错误只出现在一些配置中,但我想永远摆脱它。有什么办法可以避免这种情况吗? canvas 中的抗锯齿问题你遇到过吗?
我制作了 this fiddle,它演示了这个问题并允许您使用 canvas 的尺寸和单元格的数量。它还包含我用来绘制单元格的代码,以便您可以检查它并告诉我我是否做错了什么。
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
for (var i = 0; i < numberOfCells; ++i) {
for (var j = 0; j < numberOfCells; ++j) {
ctx.fillStyle = '#000';
ctx.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
}
}
提前致谢,
彼得
jsFiddle : https://jsfiddle.net/ngxjnywz/2/
javascript
的片段
var cellWidth = Math.ceil(canvasWidth / numberOfCells);
var cellHeight = Math.ceil(canvasHeight / numberOfCells);
根据宽度、高度和您的 numberOfCells,您有时会得到一个...让我们说 4.2 即 4,但是这会显示错误并允许出现 1 像素的空白行。因此,您需要做的就是使用 Math.ceil
函数,这将导致您的 cellWidth 和 cellHeight 始终为较大的数字,并且您不会再得到空行了
最佳解决方案是在所有填充周围添加 0.5 像素宽的描边,使用与填充相同的样式并偏移所有绘图,以便在像素中心而不是左上角渲染。
如果您添加缩放或平移,您将必须调整坐标,以便您仍然为您的绘图坐标提供中心。
最后你只能减少伪影,但在很多情况下你将无法完全消除它们。
此答案向您展示了如何删除未转换的工件 canvas。
通读并尝试了几种方法后,我决定提出自己的方法。我创建了另一个(虚拟)canvas,它的整数维度对应于网格中的单元格数量。
在其中绘制所有单元格后,我在主 canvas 上调用 context.drawImage()
并将虚拟 canvas 作为参数与偏移和缩放参数一起传递以使其适合我画的其余部分。假设浏览器会将虚拟 canvas 的图像作为一个整体(而不是单个单元格)进行缩放,我希望摆脱不需要的分隔线。
尽管我很努力,线条仍然存在。有什么建议吗?
下面是 fiddle 演示我的技巧:https://jsfiddle.net/ngxjnywz/5/
我一直在玩 canvas 元素并发现当我尝试绘制彼此相邻的 NxN 统一纯色单元格时,在某些 width/height 配置中,有模糊的白色 -他们之间的线条。
例如,这个 canvas 应该看起来是黑色的,但包含某种 网格 ,我猜想这是浏览器中错误的抗锯齿的结果。
可以这么说,这个错误只出现在一些配置中,但我想永远摆脱它。有什么办法可以避免这种情况吗? canvas 中的抗锯齿问题你遇到过吗?
我制作了 this fiddle,它演示了这个问题并允许您使用 canvas 的尺寸和单元格的数量。它还包含我用来绘制单元格的代码,以便您可以检查它并告诉我我是否做错了什么。
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
for (var i = 0; i < numberOfCells; ++i) {
for (var j = 0; j < numberOfCells; ++j) {
ctx.fillStyle = '#000';
ctx.fillRect(j * cellWidth, i * cellHeight, cellWidth, cellHeight);
}
}
提前致谢,
彼得
jsFiddle : https://jsfiddle.net/ngxjnywz/2/
javascript
的片段var cellWidth = Math.ceil(canvasWidth / numberOfCells);
var cellHeight = Math.ceil(canvasHeight / numberOfCells);
根据宽度、高度和您的 numberOfCells,您有时会得到一个...让我们说 4.2 即 4,但是这会显示错误并允许出现 1 像素的空白行。因此,您需要做的就是使用 Math.ceil
函数,这将导致您的 cellWidth 和 cellHeight 始终为较大的数字,并且您不会再得到空行了
最佳解决方案是在所有填充周围添加 0.5 像素宽的描边,使用与填充相同的样式并偏移所有绘图,以便在像素中心而不是左上角渲染。
如果您添加缩放或平移,您将必须调整坐标,以便您仍然为您的绘图坐标提供中心。
最后你只能减少伪影,但在很多情况下你将无法完全消除它们。
此答案向您展示了如何删除未转换的工件 canvas。
通读并尝试了几种方法后,我决定提出自己的方法。我创建了另一个(虚拟)canvas,它的整数维度对应于网格中的单元格数量。
在其中绘制所有单元格后,我在主 canvas 上调用 context.drawImage()
并将虚拟 canvas 作为参数与偏移和缩放参数一起传递以使其适合我画的其余部分。假设浏览器会将虚拟 canvas 的图像作为一个整体(而不是单个单元格)进行缩放,我希望摆脱不需要的分隔线。
尽管我很努力,线条仍然存在。有什么建议吗?
下面是 fiddle 演示我的技巧:https://jsfiddle.net/ngxjnywz/5/