Canvas2d has no support for arbitrary Hermite splines, but it does support cubic Bezier curves, and since cubic Beziers are 2nd order Hermite curves, we can freely convert between your data and a Bezier curve.
The maths to do this can be found over on this Primer on Bezier curves, and specifically for this problem we can convert the Hermite points ordered [p1, d1, p2, d2] as:
Hermite points [p1,d1,p2,d2] = Bezier [p1, (p1 + d1/(2*t)), (p2 - d2/(2*t)), p2]
Note that the t
value is the curve tension and controls the order of curvature at each point (the higher the tension, the higher the rate of change in curvature along the curve near the on-curve point), in this case simply 1
.
(without a tension value, your four coordinates actually define an hourglass hexagonal area on the plane, rather than a single curve, as the directional vectors are not guaranteed to be true tangents; merely vectors representing the direction of travel. The area these values define is bounded by the line {start, end} on one side, with infinitely extending boundaries along the directions of travel at the start and end).
So with that, you can draw any Hermite curve on the canvas on the canvas, using the Canvas2d API for cubic Bezier curves:
// 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();