JSFiddle - React, Tailwind, and code Playground

by RAX7

HTML

<svg id="svg"></svg>

CSS

html, body {
  height: 100%;
}

body {
  margin: 0;
  background: linear-gradient(180deg, #32067c, #150233);
}

#svg {
  width: 100%;
  height: 100%;
  opacity: 0.2;
}

.dot {
  fill: #fff;
}

.line {
  stroke: #fff;
}

JavaScript

function svgCircle(cx, cy, r, className) {
	const NS = 'http://www.w3.org/2000/svg';
  const circle = document.createElementNS(NS, 'circle');
  circle.setAttribute('cx', cx);
  circle.setAttribute('cy', cy);
  circle.setAttribute('r', r);

  if (className) {
  	circle.classList.add(className);
  }
  return circle;
}

function svgLine(x1, y1, x2, y2, className) {
  const NS = 'http://www.w3.org/2000/svg';
  const line = document.createElementNS(NS, 'line');
  line.setAttribute('x1', x1);
  line.setAttribute('y1', y1);
  line.setAttribute('x2', x2);
  line.setAttribute('y2', y2);

  if (className) {
  	line.classList.add(className);
  }
  return line;
}

class Constellation {
	constructor(SVG, x, y, size, duration, dotsQty) {
    this.size = size;
    this.pos = { x, y };

    this.dots = [];
    for (let i = 0; i < dotsQty; i++) {
      this.dots[i] = {
      	el: svgCircle(this.pos.x, this.pos.y, 3, 'dot'),
        cur: { ...this.pos },
        from: { ...this.pos },
        to: this.randomizePosition(),
      };
    }
    
    this.lines = [];
    for (let i = 0; i < dotsQty - 1; i++) {
      this.lines[i] = { el: svgLine(this.pos.x, this.pos.y, this.pos.x, this.pos.y, 'line') };
    }

    this.duration = duration * (Math.random() + 1) - duration / 2;

    this.animatePrev = 0;
  }
  
  animate(begin, now) {
  	const progress = (now - begin) / this.duration % 1;
    
    if (progress < this.animatePrev) {
    	this.dots.forEach(dot => {
      	dot.from = dot.to;
      	dot.to = this.randomizePosition();
      });
    }
    this.animatePrev = progress;

    this.dots.forEach(dot => {
    	const x = dot.from.x + (dot.to.x - dot.from.x) * progress;
      const y = dot.from.y + (dot.to.y - dot.from.y) * progress;
      dot.cur = { x, y };
      dot.el.setAttribute('cx', x);
      dot.el.setAttribute('cy', y);
    });
    
		this.lines.forEach((line, index) => {
    	const from = this.dots[index].cur;
      const to = this.dots[index + 1].cur;
     ...