HTML5画布上绘制的水平线和垂直线是两个像素宽,为什么



在HTML画布上绘制水平线和垂直线时,我无法获得渲染1像素宽线条的输出。

我已经经历了许多解决方案,包括将坐标偏移0.5,平移0.5,将画布宽度/高度乘以devicePixelRatio,甚至抓取画布图像并直接操纵像素数据。

在高DIP屏幕上,比如我的Surface Pro,偏移0.5像素,并使用devicePixelRatio缩放画布,我得到了一条清晰的1倍宽的线,但在我的标准1920 x 1080显示器上(devicePixelRatio==1(,它恢复到2倍宽。

我知道这可能是由于绘制像素边界引起的,在某些情况下,0.5的偏移量应该有帮助,但这在我所做的任何测试中都没有帮助。

这张图片显示了我在显示器上看到的内容

这是我一直在玩的电笔。这是我拍摄上述图片的项目。

为了完整起见,我在下面包含了我一直在使用的js。

const canvas = document.getElementById("canvas");
const dpi = window.devicePixelRatio;
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpi;
canvas.height = rect.height * dpi;
canvas.style.width = `${rect.width}px`;
canvas.style.height = `${rect.height}px`;
const rowHeight = 25;
const colWidth = 100;
const ctx = canvas.getContext("2d");
ctx.scale(dpi,dpi);
ctx.beginPath();
ctx.strokeStyle = '#bdbdbd';
for(let i = rowHeight + 0.5; i < canvas.height; i += rowHeight){

ctx.moveTo(0,i);
ctx.lineTo(canvas.width,i);

}
for(let i = colWidth + 0.5; i < canvas.width; i += colWidth){

ctx.moveTo(i,0);
ctx.lineTo(i,canvas.height);

}
ctx.stroke();

这是我将SVG作为图像应用于画布的另一次失败尝试,结果很有趣。

我一直在研究其他能达到预期效果的项目,比如jasmith的Glide Data Grid(他的演示在我的电脑显示器上没有问题(,但我一直无法找出我做错了什么,除非调用链中有我遗漏的东西,否则他的网格绘制例程(src/Data Grid/Data Grid render drawGridLines((第448行(看起来相当标准。

问题肯定是由CSSbox-sizing: border-box规则引起的。设置此规则时,CSSwidthheight值也将采用该大小的边框宽度。这意味着,例如,如果你有一个125x125px的位图画布,你可以通过带有1px边框的CSS将大小调整为500x500px,那么你的位图实际上会被拉伸到(500-2(x(500-2(px。从125到498的缩放比例与显示器的DPI比例不一致,因此在渲染位图时会出现抗锯齿现象。这在x1显示器上可能更为明显,因为在那里,你总是会从原始大小变为初始大小-2px,但即使在x2显示器上,你也可能面临这个问题。

所以,去掉这个规则,你就应该没事了。

最新更新