Website/script.js
2026-05-30 19:35:53 +02:00

90 lines
2.7 KiB
JavaScript

const yearElement = document.querySelector("#current-year");
const canvas = document.querySelector("#network-canvas");
if (yearElement) {
yearElement.textContent = new Date().getFullYear().toString();
}
if (canvas) {
const context = canvas.getContext("2d");
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
let animationFrame = null;
const nodes = Array.from({ length: 42 }, (_, index) => ({
x: (index * 97) % 100,
y: (index * 53) % 100,
speed: 0.08 + (index % 5) * 0.015,
phase: index * 0.7,
}));
function resizeCanvas() {
const ratio = Math.min(window.devicePixelRatio || 1, 2);
const { width, height } = canvas.getBoundingClientRect();
canvas.width = Math.max(1, Math.floor(width * ratio));
canvas.height = Math.max(1, Math.floor(height * ratio));
context.setTransform(ratio, 0, 0, ratio, 0, 0);
}
function drawNetwork(time = 0) {
const { width, height } = canvas.getBoundingClientRect();
const points = nodes.map((node) => {
const drift = prefersReducedMotion.matches ? 0 : time * 0.001 * node.speed;
return {
x: ((node.x + Math.sin(node.phase + drift) * 5 + 100) % 100) * width / 100,
y: ((node.y + Math.cos(node.phase + drift) * 5 + 100) % 100) * height / 100,
};
});
context.clearRect(0, 0, width, height);
context.fillStyle = "#070a0f";
context.fillRect(0, 0, width, height);
context.lineWidth = 1;
for (let index = 0; index < points.length; index += 1) {
for (let nextIndex = index + 1; nextIndex < points.length; nextIndex += 1) {
const first = points[index];
const second = points[nextIndex];
const distance = Math.hypot(first.x - second.x, first.y - second.y);
if (distance < 170) {
const alpha = (1 - distance / 170) * 0.22;
context.strokeStyle = `rgba(103, 232, 249, ${alpha})`;
context.beginPath();
context.moveTo(first.x, first.y);
context.lineTo(second.x, second.y);
context.stroke();
}
}
}
for (const point of points) {
context.fillStyle = "rgba(124, 247, 182, 0.88)";
context.beginPath();
context.arc(point.x, point.y, 2.2, 0, Math.PI * 2);
context.fill();
}
if (!prefersReducedMotion.matches) {
animationFrame = window.requestAnimationFrame(drawNetwork);
}
}
resizeCanvas();
drawNetwork();
window.addEventListener("resize", () => {
resizeCanvas();
if (prefersReducedMotion.matches) {
drawNetwork();
}
});
prefersReducedMotion.addEventListener("change", () => {
if (animationFrame) {
window.cancelAnimationFrame(animationFrame);
animationFrame = null;
}
drawNetwork();
});
}