<canvas id="drawing" width="800" height="600"></canvas>
#drawing {
  border: 1px solid #000;
  background: #fff;
  display: block;
  margin: 0 auto;
}
var canvas = document.getElementById("drawing");
let ctx = canvas.getContext("2d");
const w = canvas.width;
const h = canvas.height;
let an;

ctx.translate(20, 15);
ctx.scale(0.95, 0.95);
let n = 0;
let k = 17;
let s_ang = 0;
let p = [];
let cx = w / 2,
  cy = h / 2;
p.push({ x: w / 2, y: h / 2 + 10 });
p.push({ x: w / 2, y: h / 2 });

play();
function clear() {
  ctx.reset();
  ctx.translate(20, 15);
  ctx.scale(0.95, 0.95);
  cx = w / 2;
  cy = h / 2;
}
function drawline(arr, color) {
  ctx.strokeStyle = color;
  ctx.beginPath();
  ctx.moveTo(arr[0].x, arr[0].y);
  for (var i = 1; i < arr.length; i++) {
    ctx.lineTo(arr[i].x, arr[i].y);
  }
  ctx.stroke();
}
function get_s(arr) {
  let maxx = Number.NEGATIVE_INFINITY;
  let minx = Number.POSITIVE_INFINITY;
  let maxy = Number.NEGATIVE_INFINITY;
  let miny = Number.POSITIVE_INFINITY;

  arr.forEach(function (item, i, arr) {
    maxx = Math.max(maxx, item.x);
    maxy = Math.max(maxy, item.y);
    minx = Math.min(minx, item.x);
    miny = Math.min(miny, item.y);
  });

  ctx.translate(cx, cy);
  cx = (maxx - minx) / 2 + minx;
  cy = (maxy - miny) / 2 + miny;
  ctx.translate(-cx, -cy);
  let s = Math.min(w / (maxx - minx), h / (maxy - miny));
  return s;
}
function scale(s) {
  let tx = cx;
  let ty = cy;
  ctx.translate(tx - s * cx, ty - s * cy);
  cx = tx;
  cy = ty;
  ctx.scale(s, s);
}
function render() {
  let t = pw(2, n);
  let tx = p[t].x,
    ty = p[t].y;

  p.forEach(function (item, i, arr) {
    item.x -= tx;
    item.y -= ty;
  });

  let p1 = [];
  p.forEach(function (item, i, arr) {
    var rx = item.x;
    var ry = item.y;
    p1.push({
      x: rx * cosd(-s_ang) - ry * sind(-s_ang),
      y: rx * sind(-s_ang) + ry * cosd(-s_ang)
    });
  });

  if (s_ang == 90) {
    p1.pop();
    p1.reverse();
    p = p.concat(p1);
  } else {
    p1.reverse();
    p1.forEach(function (item, i, arr) {
      item.x += tx;
      item.y += ty;
    });
  }

  p.forEach(function (item, i, arr) {
    item.x += tx;
    item.y += ty;
  });

  clear();
  var s = get_s(p.concat(p1));
  scale(s);

  drawline(p, "black");
  if (s_ang != 90) drawline(p1, "blue");
}
function play() {
  render();
  if (s_ang == 90) {
    s_ang = 0;
    n++;
  } else s_ang++;

  if (n != k) an = requestAnimationFrame(play);
  else {
    cancelAnimationFrame(an);
    an = null;
  }
}
function cosd(dg) {
  return Math.cos((dg * Math.PI) / 180);
}
function sind(dg) {
  return Math.sin((dg * Math.PI) / 180);
}
function pw(w, v) {
  return Math.pow(w, v);
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.