绘制SVG贝塞尔曲线

Draw SVG Bezier curve

我有一个代表高阶贝塞尔曲线的控制点数组。
如何使用单个 SVG 路径绘制此曲线?

UPD:
例如,我有一组点:(x1, y1) (x2, y2) (x3, y3) (x4, y4) (x5, y5)。
SVG 路径在CSQT?

更新 2:解决方案
我问这个问题是为了描绘一个用 TweenMax.
动画的对象路径 后来我在 GreenSock forum.
收到回复 这里是 CodePen example.

简答:你不能。

SVG 仅内置二次曲线(二阶)和三次曲线(三阶),而您显示的曲线是四阶曲线(四阶)。 SVG 没有通用的 "N term Bezier" 绘图指令,因此您将不得不在这里做出妥协。

部分选项:

  1. 将曲线转换为(一系列)三次曲线并渲染它们。这是一个相当困难的问题,并不真正推荐。
  2. 在足够多的点对曲线进行采样,使通过这些点的多边形在人们看到的分辨率和缩放级别下看起来像一条曲线。这很容易做到,但当然你不再有 "curve",你现在有一个多边形。
  3. 如上,但点数较少,然后计算通过这些点的Catmull-Rom曲线序列,然后将这些CR曲线转换为三次贝塞尔曲线(它们是同一类型的函数,并且可以是1:1 从一个转换为另一个)。这比 2 好,因为你有一条曲线,但它可能看起来 完全 与原来的一样。当然使用的点数越多效果越好。
  4. 使用 canvas 绘制 N 次贝塞尔曲线,使用 toDataURL 函数根据结果构建图像,然后将该图像加载 as image 在你的 SVG 中。这将工作得很好,但如果您使用创建的 SVG 路径样式,使 canvas 生成相同的样式可能是一个挑战。
  5. 这个列表可能会很长,所以让我们暂时到此为止。

底线:如果您需要显示更高阶的贝塞尔曲线,SVG 不是适合使用的技术(我建议只使用 canvas 或更好的方式制作动画,例如 d3.js or paper.js。可能是后者)。

如果您最终自己滚动,采样功能会简单得可笑。曲线是参数化的,由从 0 到 1(含)的值 t 控制,可以写成嵌套线性插值:

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函数为标准线性插值函数:

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 使用积分

var points = [
  {x:50, y:100},
  {x:50, y:250},
  {x:210, y:250},
  {x:250, y:50},
  {x:380, y:150}
];

给我们:

尽管如果您需要动画漂亮的路径、具有可拖动的控制点等,Paper.js 草图会更容易使用

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

贝塞尔曲线可以用两种方式定义:使用 "C" 命令定义三次曲线或使用 "Q" 命令定义二次曲线。这些命令具有固定长度的参数,即 4 代表二次方,6 代表三次方,所以一个示例 SVG 字符串看起来像 "Q 150,-300 300,0" 你可以看到这样的 SVG 字符串 "Q 150,-300 300,0 50,150 100,200" 但这只是两个接一个的四边形曲线,参数的数量对于 "Q" 总是 4 的倍数,对于 "C".

总是 6 的倍数

list中的每个命令:

M = 移动到
L = 线托
H = 水平线到
V = 垂直线到
C =曲线图
S = 平滑曲线
Q = 二次贝塞尔曲线
T = 平滑二次贝塞尔曲线
A = 椭圆弧
Z = 关闭路径

JavaScript 或实际上在任何其他标准 API(.NET 绘图、核心图形、Android Canvas)中都有表示,但在所有这些标准中除了 Cubic 或 Quad 之外,没有其他方法。另外,根据我的经验,我从未见过具有绘制高阶贝塞尔曲线功能的绘图应用程序。因此,您最好的选择是将高阶曲线简化为 Q 或 C。