JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id='canvas' width='300' height='200'>no canvas support</canvas>
JavaScript
var cw = 300, ch = 200;
var ctrl_pnts = [{x: 10, y: 50},{x: 10, y: 100},{x: 100, y: 100},{x: 100, y: 50},{x: 110, y: 30},{x: 150, y: 110},{x: 200, y: 30}];
if (ctrl_pnts.length === 0){
alert('no control points');
return;
}
var drawSmoothLine = function(surf, ctrl_points){
var l = ctrl_points.length;
switch (l){
case 0:
case 1: //no control points
break;
case 2: //line
surf.beginPath();
surf.moveTo(ctrl_points[0].x, ctrl_points[0].y);
surf.lineTo(ctrl_points[1].x, ctrl_points[1].y);
surf.stroke();
break;
case 3: //lets use the second point as the two middle control points
surf.beginPath();
surf.moveTo(ctrl_points[0].x, ctrl_points[0].y);
surf.bezierCurveTo(ctrl_points[1].x, ctrl_points[1].y, ctrl_points[1].x, ctrl_points[1].y, ctrl_points[2].x, ctrl_points[2].y);
surf.stroke();
break;
default: //lets draw a bezier with the first 4 points, and for the rest lets create a control point to keep the line smooth
surf.beginPath();
surf.moveTo(ctrl_points[0].x, ctrl_points[0].y);
var pnt_a = ctrl_points[1], pnt_b = ctrl_points[2], pnt_end = ctrl_points[3];
surf.bezierCurveTo(pnt_a.x, pnt_a.y, pnt_b.x, pnt_b.y, pnt_end.x, pnt_end.y);
ctrl_points = ctrl_points.slice(0);
l = ctrl_points.length;
pnt_b = ctrl_points[2];
var i = 5
for (; i < l; i += 2){
pnt_a = {x: pnt_end.x + (pnt_end.x - pnt_b.x), y: pnt_end.y + (pnt_end.y - pnt_b.y)};
pnt_b = ctrl_points[i - 1];
pnt_end = ctrl_points[i];
surf.bezierCurveTo(pnt_a.x, pnt_a.y, pnt_b.x, pnt_b.y, pnt_end.x, pnt_end.y);
}
if (i == l){ //a last lonely point, lets use the calculated pnt_a as pnt_b
pnt_a = {x: pnt_end.x + (pnt_end.x - pnt_b.x), y: pnt_end.y + (pnt_end.y - pnt_b.y)};
pnt_b = pnt_a;
pnt_end = ctrl_points[l - 1];
...