// size of the tangent
var t = 1 / 5;// points array
var p = [{x: 100,y: 100
}, {x: 250,y: 150
}, {x: 300,y: 300
}, {x: 450,y: 250
}, {x: 510,y: 140
}, {x: 590,y: 250
}, {x: 670,y: 140
}];function controlPoints(p) {// given the points array p calculate the control points for the cubic Bezier curvesvar pc = [];for (var i = 1; i < p.length - 1; i++) {var dx = p[i - 1].x - p[i + 1].x; // difference xvar dy = p[i - 1].y - p[i + 1].y; // difference y// the first control pointvar x1 = p[i].x - dx * t;var y1 = p[i].y - dy * t;var o1 = {x: x1,y: y1};// the second control pointvar x2 = p[i].x + dx * t;var y2 = p[i].y + dy * t;var o2 = {x: x2,y: y2};// building the control points arraypc[i] = [];pc[i].push(o1);pc[i].push(o2);}return pc;
}function drawCurve(p) {var pc = controlPoints(p); // the control points arraylet d =`M${p[0].x},${p[0].y}
Q${pc[1][1].x},${pc[1][1].y}, ${p[1].x},${p[1].y}
`if (p.length > 2) {// central curves are cubic Bezierfor (var i = 1; i < p.length - 2; i++) {d += `C${pc[i][0].x}, ${pc[i][0].y}, ${pc[i + 1][1].x}, ${pc[i + 1][1].y}, ${p[i + 1].x},${p[i + 1].y}`;}// the first & the last curve are quadratic Beziervar n = p.length - 1;d+= `Q${pc[n - 1][0].x}, ${pc[n - 1][0].y}, ${p[n].x}, ${p[n].y}`;}return d
}thePath.setAttribute("d", drawCurve(p))
svg{border:solid; fill:none;stroke:black;}
<svg id = 'svg' viewBox="0 0 800 400"><path id="thePath" />
</svg>