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;
...