Curves Test

by soulwire

HTML

<script src="https://rawgit.com/soswow/fit-curves/master/lib/fit-curve.js"></script>
<script>
window.fadeOutPowerCoeff = 0.5229226350784302;
window.fadeInPowerCoeff = 0.3853868246078491;
window.fadeOut = {
  "start_point": 0,
  "end_point": 1,
  "controlpoints": [
    {
      "x": 0,
      "y": 1
    },
    {
      "x": 0.006,
      "y": 0.9311599233714227
    },
    {
      "x": 0.047,
      "y": 0.797881992944149
    },
    {
      "x": 0.285,
      "y": 0.4812889448388062
    },
    {
      "x": 0.583,
      "y": 0.24584145590851758
    },
    {
      "x": 0.999,
      "y": 0.0005230474338083768
    }
  ] 
};
window.fadeIn = {
  "start_point": 0,
  "end_point": 1,
  "controlpoints": [
    {
      "x": 0,
      "y": 0
    },
    {
      "x": 0.025999999999999995,
      "y": 0.2449832468518358
    },
    {
      "x": 0.151,
      "y": 0.4825993448935252
    },
    {
      "x": 0.485,
      "y": 0.7566391897470297
    },
    {
      "x": 0.999,
      "y": 0.9996144946796999
    }
  ]
};
</script>

CSS

html, body {
  margin: 0;
}

Babel + JSX

const canvas = document.createElement('canvas');
const scale = window.devicePixelRatio;
const width = window.innerWidth;
const height = window.innerHeight;
document.body.appendChild(canvas);
canvas.width = width * scale;
canvas.height = height * scale;
canvas.style.width = width + 'px';
canvas.style.height = height + 'px';
const g = canvas.getContext('2d');
g.scale(scale, scale);

const drawCurve = (points, x, y, width, height) => {
	g.save();
  g.translate(x, y);
  g.fillStyle = 'rgba(255,255,255,0.75)';
  g.fillRect(0, 0, width, height);
  g.beginPath();
  points.forEach((p, i) => {
  	x = p.x * width;
    y = height - p.y * height;
    if (i === 0) {
    	g.moveTo(x, y);
    } else {
    	g.lineTo(x, y);
    }
  });
  g.stroke();
  g.restore();
};

const createCurvePoints = (powerCoeff, fadeOut = false) => {
	const points = [];
  const total = 1000;
	for (let t, y, i = 0; i < total; i++) {
  	t = i / total;
    y = Math.pow(t, powerCoeff);
    if (fadeOut) y = 1 - y;
    points.push({ x: t, y });
  }
  return points;
};

drawCurve(fadeOut.controlpoints, 10, 10, 200, 100);
drawCurve(fadeIn.controlpoints, 10, 120, 200, 100);

const fadeOutPoints = createCurvePoints(fadeOutPowerCoeff, true);
const fadeInPoints = createCurvePoints(fadeInPowerCoeff, false);

drawCurve(fadeOutPoints, 220, 10, 200, 100);
drawCurve(fadeInPoints, 220, 120, 200, 100);

// TODO approximate bezier
const c1 = fitCurve(fadeOutPoints.map(p => [p.x, p.y]), 0.001);
const c2 = fitCurve(fadeInPoints.map(p => [p.x, p.y]), 0.001);
drawCurve(c1[0].map(a => ({x:a[0], y:a[1]})), 220, 10, 200, 100);
drawCurve(c2[0].map(a => ({x:a[0], y:a[1]})), 220, 120, 200, 100);