* {
  margin: 0; padding: 0;
}
var canvas = document.createElement("canvas"),
  c = canvas.getContext("2d");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);

c.fillStyle = "gray";
c.fillRect(0, 0, canvas.width, canvas.height);

c.strokeStyle = 'white';
c.lineWidth = 2;

c.beginPath();
c.moveTo(0, 0);
bezierSkin([ 10, 10, 210, 10, 10, 300, 210, 300 ], false);
bezierSkin([ 200, 10, 330, 10, 250, 300 ]);
bezierSkin(
  Array(30).fill(0)
  .map((a, b) => (b % 2 == 0) * 300 + Math.random() * 300)
);
c.stroke();

// array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
  var avg = calcAvgs(bez), 
      leng = bez.length,
      i, n;

  if (closed) {
    c.moveTo(avg[0], avg[1]);
    for (i = 2; i < leng; i += 2) {
      n = i + 1;
      c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
    }
    c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
  } else {
    c.moveTo(bez[0], bez[1]);
    c.lineTo(avg[0], avg[1]);
    for (i = 2; i < leng - 2; i += 2) {
      n = i + 1;
      c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
    }
    c.lineTo(bez[leng - 2], bez[leng - 1]);
  }
}


// create anchor points by averaging the control points
function calcAvgs(p) {
  var avg = [],
      leng = p.length, prev;
  for (var i = 2; i < leng; i++) {
    prev = i - 2;
    avg.push((p[prev] + p[i]) / 2);
  }
  // close
  avg.push((p[0] + p[leng - 2]) / 2);
  avg.push((p[1] + p[leng - 1]) / 2);
  return avg;
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.