为什么 HTML Canvas 圆角 lineCap 最后一段失败?

发布于 2024-10-09 16:06:25 字数 960 浏览 1 评论 0原文

使用 HTML Canvas 如果你画一条像这样的虚线:

ctx.lineWidth   = 40;
ctx.lineCap     = 'round';
ctx.strokeStyle = 'red';

ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(150,200);
ctx.moveTo(200,300);
ctx.lineTo(250,400);
ctx.moveTo(300,500);
ctx.lineTo(350,600);
ctx.closePath();
ctx.stroke();

那么结果是这样的:

虚线,前两个破折号使用圆线帽,最后一个破折号使用平头帽
(来源:phrogz.net

正如您在 < a href="http://phrogz.net/tmp/canvas_broken_rounded_rinkle.html" rel="nofollow noreferrer">此测试页面,在最后一个之后添加“多余的”moveTo 调用lineTo 修复了最后一个线段以使用圆角大写字母。

我准备将此作为一个错误提交,但后来我发现该行为在 Safari v5、Chrome v8、FireFox v3.6 和 v4.0b 上是相同的。这让我相信这是故意的。

标准中的哪个位置指定了此行为,以及(如果您能辨别)为什么如此指定?

With the HTML Canvas if you draw a dotted line like this:

ctx.lineWidth   = 40;
ctx.lineCap     = 'round';
ctx.strokeStyle = 'red';

ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(150,200);
ctx.moveTo(200,300);
ctx.lineTo(250,400);
ctx.moveTo(300,500);
ctx.lineTo(350,600);
ctx.closePath();
ctx.stroke();

then the result is this:

Dashed line with first two dashes using rounded line caps and last dash using butt caps
(source: phrogz.net)

As you can see on this test page, adding a "superfluous" moveTo call after the last lineTo fixes the last line segment to use rounded caps.

I was prepared to file this as a bug, but then I found that the behavior is identical on Safari v5, Chrome v8, and FireFox v3.6 and v4.0b. This leads me to believe that it is intentional.

Where in the standard is this behavior specified, and (if you can discern it) why was it specced as such?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

他不在意 2024-10-16 16:06:25

以下是canvas 规范(第 9 节,路径)

moveTo(x, y) 方法必须创建一个新的子路径,并将指定点作为其第一个(也是唯一的)点。

lineTo(x, y) 方法...必须使用直线将子路径中的最后一个点连接到给定点 (x, y),然后必须添加给定点(x, y) 到子路径。

closePath() 方法...必须将最后一个子路径标记为闭合...这相当于添加一条将最后一个点连接回第一个点的直线,从而“闭合”形状...

每个 moveTo 调用都会创建一个新的子路径,从而结束之前的子路径。在您的情况下,前两个片段以这种方式结束。对于最后一段,调用 closePath 通过沿相反方向绘制另一段来“关闭”该段,因此您看到的结果是 - 不是一个段,而是两个重叠的段。添加另一个 moveTo 会像其他段一样结束此段,因此您会看到预期的圆形线帽。

Here are the relevant definitions from the canvas spec (section 9, paths):

The moveTo(x, y) method must create a new subpath with the specified point as its first (and only) point.

The lineTo(x, y) method ... must connect the last point in the subpath to the given point (x, y) using a straight line, and must then add the given point (x, y) to the subpath.

The closePath() method ... must mark the last subpath as closed ... this is equivalent to adding a straight line connecting the last point back to the first point, thus "closing" the shape ...

Each moveTo call creates a new subpath, thus ending the previous subpath. In your case, the first two segments are ended this way. For the final segment, calling closePath "closes" the segment by drawing another segment in the reverse direction, hence the result you are seeing -- there is not one segment but rather two overlapping segments. Adding another moveTo ends this segment just like the others, so you see the rounded line cap as expected.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文