HTML5、画布和strokeRect:一些线条太窄且模糊

10
一个非常简单的Canvas用法:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

ctx.strokeStyle = "#CCCC00";
ctx.lineWidth = 3;
ctx.strokeRect(0, 0, width, height);

返回一个上边和左边都更细的矩形:

enter image description here

为什么会这样?需要用padding偏移吗?这很烦人。

2个回答

31

有两件事。

首先,奇数的lineWidth(1, 3, 5, ...)永远无法与整数像素值完美匹配。这是因为X和Y指的是像素之间的空间,而不是它们的中心。所以从[1,1][1,10]的描边线会将一半溢出到左侧列的像素中,另一半溢出到右侧。如果你将该线条从[1.5,1]绘制到[1.5,10],那么它就会完美地填满整个像素列,一半向左,一半向右。

任何奇数宽度都会显示这种行为,但偶数宽度不会,因为它们在每一侧都填充了一个完整的像素,看起来很干净。


其次,该框被画布的顶部遮挡住了。当你将3像素的描边居中于[0,0]时,它会向上和向左溢出到[-1.5,-1.5],这超出了画布的可见范围。因此,它看起来只有应有厚度的一半。
看到这里的差异证明:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

// original box, eclipsed by canvas bounds
ctx.strokeStyle = "#CC0000";
ctx.lineWidth = 3;
ctx.strokeRect(0, 0, 20, 20);

// moved from canvas bounds
ctx.strokeStyle = "#CC0000";
ctx.lineWidth = 3;
ctx.strokeRect(25, 25, 20, 20);

// drawn on half pixel coordinates to prevent blurry lines with odd integer line widths.
ctx.strokeStyle = "#CC0000";
ctx.lineWidth = 3;
ctx.strokeRect(50.5, 50.5, 20, 20);
body { margin: 10px }
<canvas id="canvas" width="100" height="100"></canvas>

应该渲染为:

这个

three boxes

第一个就像你的代码。第二个则是从左上角移开,以显示其宽度的一致性。第三个演示了如何渲染3像素的描边而不产生亚像素模糊。

太棒了!谢谢你的解释。 - Mr. Polywhirl

0

实际上它不会是线的1/3,而是一半。 - Alex Wayne
1
@AlexWayne,线宽不是以像素为单位吗? 怎么可能只呈现1.5个像素? 编辑-哦天啊,太恶心了,抗锯齿处理3像素的线...什么鬼 - Langdon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接