绘制SVG贝塞尔曲线

Leg*_*tin 9 html svg bezier tweenmax gsap

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

在此输入图像描述

UPD:
例如,我有一组点:(x1,y1)(x2,y2)(x3,y3)(x4,y4)(x5,y5).
如何SVG-路径看起来像的条款C,S,QT

UPD 2:解决方案
我问这个问题描绘了一个用TweenMax动画的对象路径.
后来我收到了GreenSock论坛的回复.
这是CodePen示例.

Mik*_*ans 10

简短的回答:你做不到.

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

一些选择:

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

底线:如果你需要显示更高阶的贝塞尔曲线,SVG不是一个合适的技术(我建议你只使用画布做动画,或者更好,比如d3.jspaper.js.可能是后者).

如果你最终自己动手,那么采样功能非常简单.曲线是参数化的,由t从0到1(包括)的值控制,可以写为嵌套线性插值:

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);
}
Run Code Online (Sandbox Code Playgroud)

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)
  };
}
Run Code Online (Sandbox Code Playgroud)

还有一个简单的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}
];
Run Code Online (Sandbox Code Playgroud)

给我们:

在此输入图像描述

虽然如果你需要动画漂亮的路径,可拖动的控制点等,Paper.js草图会更容易使用.