circle/triangle lerp

by greg gorlen

JavaScript

"use strict";

const canvas = document.createElement("canvas");
canvas.width = innerWidth;
canvas.height = innerHeight;
const size = Math.min(canvas.width, canvas.height) / 3;
document.body.style.margin = 0;
document.body.appendChild(canvas);
const ctx = canvas.getContext("2d");
const rad = d => d * Math.PI / 180;
const lerp = (v0, v1, t) => (1 - t) * v0 + t * v1;
const tri = [];
const circ = [];
const points = [];
const triPoints = [];

for (let i = 0; i <= 360; i += 120) {
  triPoints.push({
    x: size * Math.cos(rad(i)),
    y: size * Math.sin(rad(i))
  });
}

for (let i = 0; i < triPoints.length - 1; i++) {
  for (let t = 0; t < 1; t += 0.01) {
  	tri.push({
      x: lerp(triPoints[i].x, triPoints[i+1].x, t),
      y: lerp(triPoints[i].y, triPoints[i+1].y, t)
    });
  }
}

for (let i = 1; i < 360; i += 360 / tri.length) {
  circ.push({
  	x: size * Math.cos(rad(i)),
  	y: size * Math.sin(rad(i))
  });

  points.push({
  	x: size * Math.cos(rad(i)),
  	y: size * Math.sin(rad(i))
  });
}

ctx.translate(canvas.width / 2, canvas.height / 2);
ctx.lineWidth = 8;
let t = 0;
let dir = 1;

(function render() {
  ctx.clearRect(-canvas.width, -canvas.height, canvas.width * 2, canvas.height * 2);
  
  ctx.beginPath();
  
  for (let i = 0; i < points.length; i++) {
  	ctx.lineTo(points[i].x, points[i].y);
    points[i].x = lerp(circ[i].x, tri[i].x, t);
    points[i].y = lerp(circ[i].y, tri[i].y, t);
  }
  
  t += 0.01 * dir;
  
  if (t >= 1 || t <= 0) {
  	dir *= -1;
  }
  
  ctx.closePath();
  ctx.stroke();
  
  requestAnimationFrame(render);
})();