Canvas2d不支持任意Hermite样条曲线,但它确实支持三次Bezier曲线,并且由于三次Beziers是二阶Hermite曲线,我们可以在数据和贝塞尔曲线之间自由转换。
做到这一点的数学可以在这个Primer on Bezier curves找到了,并专门针对这个问题,我们可以转换埃尔米特点有序[P1,D1,P2,D2]为:
注意,值是曲线张力并控制每个点处的曲率顺序(张力越高,曲线上点附近的曲率变化率越高),在这种情况下仅为1
。
(没有张力值,您的四个坐标实际上在平面上定义了一个沙漏六角形区域,而不是单个曲线,因为方向矢量不能保证是真正的切线;只是表示行进方向的矢量。这些值定义的区域由一边的{start,end}行界定,在开始和结束时沿着行进方向具有无限延伸的边界)。
所以与,可以绘制在画布上的画布上的任何埃尔米特曲线,使用用于三次贝塞尔曲线Canvas2d API:
// Hermite data
var p1 = ..., d1 = ..., p2 = ..., d2 = ...;
var cmpoints = [p1.x, p1.y, d1.x, d1.y, p2.x, p2.y, d2.x, d2.y];
// Bezier data
var tension = 1;
var tensionFactor = 2 * tension;
var bpoints = [
p1.x,
p1.y,
p1.x + d1.x/tensionFactor,
p1.y + d1.y/tensionFactor,
p2.x - d2.x/tensionFactor,
p2.y - d2.y/tensionFactor,
p2.x,
p2.y
]
// Draw code (where we assume you already
// have your canvas context as "ctx")
ctx.beginPath();
ctx.moveTo.apply(bpoints.slice(0,2));
ctx.bezierCurveTo.apply(bpoints.slice(2);
ctx.stroke();
请提供一个[最小,完整,可验证](http://stackoverflow.com/help/mcve)尝试,所以我们可以尝试解决你的问题,并解释为什么你自己的尝试失败 - 这样你可以学习一些对你未来发展有用的东西,并且得到这个单一问题的答案。 –
这[小提琴](http://jsfiddle.net/jmchen/m9k8qn0v/1/)可能会有所提示。 –
[这里](http://stackoverflow.com/a/15528789/1693593)是一个Catmull-Rom实现与张力(又名基数样条)。 – K3N