首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >绘制SVG Bezier曲线

绘制SVG Bezier曲线
EN

Stack Overflow用户
提问于 2016-06-03 14:24:26
回答 2查看 4.7K关注 0票数 13

我有一个控制点数组,表示一个高阶Bezier曲线.

如何使用一条SVG路径绘制这条曲线?

UPD:

例如,我有一组点:(x1,y1) (x2,y2) (x3,y3) (x4,y4) (x5,y5)。

CSQT的角度来看,SVG-path会是什么样子?

UPD 2:解决方案

我问这个问题是为了描绘一个用TweenMax动画的对象路径。

后来,我在GreenSock论坛上收到了回复。

这是CodePen实例

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-06-03 17:28:51

简短的回答:你不能。

SVG只构建了二次曲线(2阶)和三次曲线(3阶),而你显示的曲线是四次曲线(4阶)。SVG没有通用的"N术语Bezier“抽签指令,所以您必须在这里妥协。

一些备选方案:

  1. 将曲线转换为(一系列)三次曲线并进行渲染。这是一个相当困难的问题,并不是真正的推荐。
  2. 在足够的点上采样你的曲线,这样通过这些点的多边形看起来就像一条曲线,在分辨率和缩放水平上,人们会看到它。这是容易做到的,但当然,你不再有一个“曲线”,你现在有一个多边形。
  3. 如前所述,但点较少,然后计算通过这些点的Catmull曲线序列,然后将这些CR曲线转换为三次Bezier (它们是相同类型的函数,可以从一个转换到另一个)。这比2更好,因为你有一条曲线,但它看上去可能和原来的不太一样。当然,你使用的分数越多,效果就越好。
  4. 使用画布绘制N度Bezier曲线,使用toDataURL函数从结果中构建一个图像,然后将该图像作为图像加载到SVG中。这将非常好地工作,但是如果您使用创建的SVG路径样式,让画布生成相同的样式可能是一个挑战。
  5. 这个列表可能会很长,所以我们现在就停下来。

底线:如果您需要显示更高阶的Bezier曲线,SVG并不是一种适合使用的技术(我建议您只使用画布来制作动画,或者更好一些,比如d3.jspaper.js。可能是后者)。

如果你的结果是滚动你自己的,抽样功能是可笑的简单。曲线是参数化的,由一个从0到1(包括在内)的值t控制,可以写成嵌套的线性插值:

代码语言:javascript
复制
getCurvePoint(t, points) {
  if (points.length === 1) return points[0];
  var newpoints = [];
  for(var i=0,j=1; j<points.length; i++,j++) {
    newpoints[i] = lerp2d(t, points[i], points[j]);
  }
  return getCurvePoint(t,newpoints);
}

lerp函数是标准的线性插值函数:

代码语言:javascript
复制
lerp(ratio, start, end) {
  return ratio*start + (1-ratio)*end;
}

lerp2d(ratio, start, end) {
  return {
    x: lerp(ratio, start.x, end.x),
    y: lerp(ratio, start.y, end.y)
  };
}

和一个简单的jsbin示例:使用点的http://jsbin.com/pesutibefu/edit?html,js,output

代码语言:javascript
复制
var points = [
  {x:50, y:100},
  {x:50, y:250},
  {x:210, y:250},
  {x:250, y:50},
  {x:380, y:150}
];

给我们:

虽然Paper.js草图将更容易处理,如果您需要动画漂亮的路径,具有可拖动的控制点等。

票数 12
EN

Stack Overflow用户

发布于 2016-06-03 17:57:37

SVG不支持二次曲线和三次曲线以外的Bezier曲线。因此,在命令(C、S、Q或T)方面没有表示。

Bezier曲线可以用两种方式定义:三次使用"C“命令,二次定义使用"Q”命令。这些命令有固定的参数长度,二次参数为4,立方参数为6,因此一个示例SVG字符串将类似于"Q 150,- 300 ,0,0“-您可以看到一个"Q 150,-300,0 50,150 100,200",但这只是一个接一个的两个四曲线,参数的数量总是"Q”的4倍和"C“的6的倍数。

列表中的每个命令

M=移动

L= lineto

H=水平线

V=垂直线

C=曲线

S=光滑曲线

Q=二次Bézier曲线

T=光滑二次Bézier曲线

A=椭圆弧

Z=闭合路径

JavaScript中或实际上在任何其他标准API (.NET绘图、核心图形、Android )中都有一个表示,但在所有这些中,除了立方体或Quad之外,没有任何其他方法。此外,在我的经验中,我从未见过有一个绘图应用程序具有绘制更高阶Bezier曲线的功能。所以你最好的选择是把高阶曲线简化成Q或C。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37616929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档