HTML5 Canvas - 二次曲线的意外效果

发布于 2024-12-23 05:42:06 字数 3041 浏览 1 评论 0原文

我最近一直在开发一个涂鸦应用程序,只是为了好玩。在尝试了多种使用鼠标给出的采样点绘制平滑曲线的方法之后,我决定使用二次曲线。

我必须承认,我对这些曲线的理解并不是最佳的,但我认为我理解它们是如何工作的。我无法理解的是,当我绘制一条上升然后突然下降的曲线时,曲线的峰值不再是圆形的(它看起来是扁平的)。

演示可以更好地理解我在说什么:链接到 JCanvas 沙箱

如果删除曲线的最后一部分(从 cx11 到 y15): 链接到另一个 JCanvas 沙箱。看起来不错,但是当您添加下一个控制点和终点时,您会得到这种奇怪的效果。

注意:我没有使用 JCanvas,但它有同样的错误,而且沙箱很方便。我猜它来自我得到的坐标,但我无法解释,也找不到解决方法/黑客让它看起来更圆润......

对于那些不喜欢沙箱的人,这里有一个简短的版本导致问题的坐标:

x1:216,y1:98, CX1:216,CY1:97, x2:216,y2:98, CX2:216,CY2:99, x3:215,y2:103,

有什么想法吗?欢迎数学方面的内容。我已经做了一些关于这个问题的搜索和阅读,但没有找到任何类似的东西。

--

更新

正如 Simon 指出的,我使用的是 Chrome 16,并且我已经使用 Firefox 4 和最新的 Safari 测试了该示例,并且存在该错误。我尝试使用 Opera,看起来不错。

我对此感到相当沮丧,因为这个错误也出现在 iPad 上,而且我正在尝试开发一个移动网络应用程序,所以我有点陷入困境。

有解决方法/黑客的想法吗?

I've been working on a doodling app recently just for kicks. After trying many methods to draw smooth curves with the sample points given by the mouse, I've settled for something using Quadratic Curve.

I must admit, my understanding of these curves is not optimal but I think I understood how they work. What I can't understand is that when I draw a curve which goes up and then suddenly down, the peak of the curve is not rounded anymore (it looks flattened).

A demo is much better to understand what I'm talking about: link to JCanvas sandbox

If you remove the last part of the curve (from cx11 to y15): link to another JCanvas sandbox. It looks fine, but when you add the next control point and end point, you get this weird effect.

Note: I'm not using JCanvas, but it has the same bug and the sandbox is handy. I guess it comes from the coordinates I get, but I can't explain and can't find a workaround/hack to make it look rounded...

For those who can't be bothered with the sandbox, here's a short version of the coordinates which are causing the problem:

x1: 216, y1: 98,
cx1: 216, cy1: 97,
x2: 216, y2: 98,
cx2: 216, cy2: 99,
x3: 215, y2: 103,

Any ideas on why? Mathematicals stuff are welcome. I've done a bit of searching and reading about the problem but didn't find anything about something similar.

--

Update

As Simon pointed out, I'm using Chrome 16 and I've tested the example with Firefox 4 and the latest Safari and the bug is there. I tried with Opera and it looks fine.

I'm rather frustrated about that as the bug is also on the iPad and I was trying to do a mobile web app so I'm sort of stuck.

Any ideas for a workaround/hack?

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

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

发布评论

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

评论(1

流殇 2024-12-30 05:42:06

找到了解决方法。这是那些愚蠢的“零方法”错误之一,我真的不知道它们的正确名称。如果两点之间的连接是一条非常小的垂直线并且 Safari 会感到困惑,那么很难绕过拐角。

在您的问题所在位置有一条 1 像素高的垂直线曲线需要进行圆角化。

如果一条二次曲线与下一条二次曲线之间的 X 目的地相同,则 safari 会给您带来问题。所以这很糟糕:

ctx.beginPath();
ctx.moveTo(161,178);
ctx.quadraticCurveTo(215, 102, 216, 100);
ctx.quadraticCurveTo(216, 98, 216, 98);
ctx.quadraticCurveTo(216, 99, 215, 103); // I have the same X as the previous quadratic
ctx.quadraticCurveTo(213, 107, 211, 120);
ctx.quadraticCurveTo(209, 133, 209, 145);
ctx.stroke();

请参见这里: http://jsfiddle.net/Ws6UY/

所以如果我们只是改变值最小的金额:

ctx.beginPath();
ctx.moveTo(161,178);
ctx.quadraticCurveTo(215, 102, 216, 100);
ctx.quadraticCurveTo(216, 98, 216, 98);
ctx.quadraticCurveTo(216.01, 99, 215, 103); // 216.01 is not the same X as 216!
ctx.quadraticCurveTo(213, 107, 211, 120);
ctx.quadraticCurveTo(209, 133, 209, 145);
ctx.stroke();

请参见此处:http://jsfiddle.net/Ws6UY/1/

多么愚蠢啊!要保持 safari/iOS 浏览器正常工作,您所要做的就是确保 x(可能还有 y)值与最后一点不同。

Found a workaround. It's one of those silly as-blah-approaches-zero bugs, I don't really know the proper name for them. It's hard to round a corner if the connection between two points is a very tiny vertical line and Safari gets confused.

At the location of your problem there is a 1 pixel high vertical line curve that needs to be rounded.

If the X destination is identical between one quadratic curve and the next, safari will give you problems. So this is bad:

ctx.beginPath();
ctx.moveTo(161,178);
ctx.quadraticCurveTo(215, 102, 216, 100);
ctx.quadraticCurveTo(216, 98, 216, 98);
ctx.quadraticCurveTo(216, 99, 215, 103); // I have the same X as the previous quadratic
ctx.quadraticCurveTo(213, 107, 211, 120);
ctx.quadraticCurveTo(209, 133, 209, 145);
ctx.stroke();

See it here: http://jsfiddle.net/Ws6UY/

So if we just change that value the tiniest amount:

ctx.beginPath();
ctx.moveTo(161,178);
ctx.quadraticCurveTo(215, 102, 216, 100);
ctx.quadraticCurveTo(216, 98, 216, 98);
ctx.quadraticCurveTo(216.01, 99, 215, 103); // 216.01 is not the same X as 216!
ctx.quadraticCurveTo(213, 107, 211, 120);
ctx.quadraticCurveTo(209, 133, 209, 145);
ctx.stroke();

See it here: http://jsfiddle.net/Ws6UY/1/

How silly! All you have to do to keep safari/iOS browsers working is make sure that the x (And probably y) values are not identical to the last point.

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