* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  height: 100vh;
  display: grid;
  place-items: center;
}

svg {
  width: 75vmin;
  height: 75vmin;
  overflow: visible;
}
import Quadtree from "https://cdn.skypack.dev/@timohausmann/quadtree-js@1.2.4";
import {
  createQtGrid,
  randomBias,
  randomSnap,
  random
} from "https://cdn.skypack.dev/@georgedoescode/generative-utils";
import { SVG } from "https://cdn.skypack.dev/@svgdotjs/svg.js";

const width = 200;
const height = 200;

const svg = SVG().viewbox(0, 0, width, height).addTo("body");

const colors = ["#7257fa", "#ffd53d", "#1D1934", "#F25C54"];

let step = 0;
let points;
let grid;

function animate() {
  if (step === 0) {
    svg.clear();

    const focus = {
      x: random(0, width),
      y: random(0, height)
    };

    points = [...Array(100)].map(() => {
      return {
        x: randomBias(0, width, focus.x, 1),
        y: randomBias(0, height, focus.y, 1),
        width: 1,
        height: 1
      };
    });

    points.forEach((point) => {
      svg
        .circle(2)
        .cx(point.x)
        .cy(point.y)
        .fill("#1D193")
        .attr("class", "outline");
    });
  }

  if (step === 1) {
    grid = createQtGrid({
      width,
      height,
      points,
      gap: 2,
      maxQtLevels: 4
    });

    grid.areas.forEach((area) => {
      svg
        .rect(area.width, area.height)
        .x(area.x)
        .y(area.y)
        .fill("none")
        .stroke("#9F9CB0")
        .attr("class", "outline");
    });
  }

  if (step === 2) {
    const density = random(0.375, 0.75);
    grid.areas.forEach((area) => {
      if (random(0, 1) > density) {
        if (random(0, 1) > 0.5) {
          svg
            .rect(area.width, area.height)
            .x(area.x)
            .y(area.y)
            .fill(random(colors));
        } else {
          svg
            .circle(Math.min(area.width, area.height))
            .x(area.x)
            .y(area.y)
            .fill(random(colors));
        }
      }
    });
  }

  if (step === 3) {
    document.querySelectorAll(".outline").forEach((el) => {
      el.style.opacity = 0;
    });
  }

  step < 3 ? step++ : (step = 0);

  setTimeout(() => {
    animate();
  }, 750);
}

animate();

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.