89 lines
2.2 KiB
JavaScript
89 lines
2.2 KiB
JavaScript
|
import gsap from "https://cdn.skypack.dev/gsap@3.6.0";
|
||
|
import { spline } from "https://cdn.skypack.dev/@georgedoescode/spline@1.0.1";
|
||
|
import SimplexNoise from "https://cdn.skypack.dev/simplex-noise@2.4.0";
|
||
|
|
||
|
const simplex = new SimplexNoise();
|
||
|
|
||
|
const path = document.querySelector("path");
|
||
|
const root = document.documentElement;
|
||
|
|
||
|
let hueNoiseOffset = 0;
|
||
|
|
||
|
let noiseStep = 0.005;
|
||
|
|
||
|
const points = createPoints();
|
||
|
|
||
|
(function animate() {
|
||
|
path.setAttribute("d", spline(points, 1, true));
|
||
|
|
||
|
for (let i = 0; i < points.length; i++) {
|
||
|
const point = points[i];
|
||
|
|
||
|
const nX = noise(point.noiseOffsetX, point.noiseOffsetX);
|
||
|
const nY = noise(point.noiseOffsetY, point.noiseOffsetX);
|
||
|
const x = map(nX, -1, 1, point.originX - 20, point.originX + 20);
|
||
|
const y = map(nY, -1, 1, point.originY - 20, point.originY + 20);
|
||
|
|
||
|
point.x = x;
|
||
|
point.y = y;
|
||
|
|
||
|
point.noiseOffsetX += noiseStep;
|
||
|
point.noiseOffsetY += noiseStep;
|
||
|
}
|
||
|
|
||
|
const hueNoise = noise(hueNoiseOffset, hueNoiseOffset);
|
||
|
const hue = map(hueNoise, -1, 1, 0, 360);
|
||
|
|
||
|
root.style.setProperty("--startColor", `hsl(${hue}, 100%, 75%)`);
|
||
|
root.style.setProperty("--startColor", `hsl(${hue + 60}, 100%, 75%)`);
|
||
|
document.body.style.background = `hsl(${hue + 60}, 75%, 5%)`;
|
||
|
|
||
|
hueNoiseOffset += noiseStep / 6;
|
||
|
|
||
|
requestAnimationFrame(animate);
|
||
|
})();
|
||
|
|
||
|
function random(min, max) {
|
||
|
return Math.random() * (max - min) + min;
|
||
|
}
|
||
|
|
||
|
function map(n, start1, end1, start2, end2) {
|
||
|
return ((n - start1) / (end1 - start1)) * (end2 - start2) + start2;
|
||
|
}
|
||
|
|
||
|
function noise(x, y) {
|
||
|
return simplex.noise2D(x, y);
|
||
|
}
|
||
|
|
||
|
function createPoints() {
|
||
|
const points = [];
|
||
|
const numPoints = 6;
|
||
|
const angleStep = (Math.PI * 2) / numPoints;
|
||
|
const rad = 75;
|
||
|
|
||
|
for (let i = 1; i <= numPoints; i++) {
|
||
|
const theta = i * angleStep;
|
||
|
|
||
|
const x = 100 + Math.cos(theta) * rad;
|
||
|
const y = 100 + Math.sin(theta) * rad;
|
||
|
|
||
|
points.push({
|
||
|
x: x,
|
||
|
y: y,
|
||
|
originX: x,
|
||
|
originY: y,
|
||
|
noiseOffsetX: random(0, 1000),
|
||
|
noiseOffsetY: random(0, 1000)
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return points;
|
||
|
}
|
||
|
|
||
|
document.querySelector("path").addEventListener("mouseover", () => {
|
||
|
noiseStep = 0.01;
|
||
|
});
|
||
|
|
||
|
document.querySelector("path").addEventListener("mouseleave", () => {
|
||
|
noiseStep = 0.005;
|
||
|
});
|