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