Files
Bratonien-Adventskalender/adventskalender/shared/js/glitter.js

114 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Bratonien Glitter Hover Effekt strikt nach data-day gruppiert
document.addEventListener("DOMContentLoaded", () => {
// Alle relevanten Elemente einsammeln
const elems = document.querySelectorAll(".door, .openfield, .fluegel");
// nach Tag gruppieren
const groupsByDay = {};
elems.forEach(el => {
const day = el.dataset.day;
if (!groupsByDay[day]) {
groupsByDay[day] = [];
}
groupsByDay[day].push(el);
});
// für jede Tagesgruppe Hover + Glitzer setzen
Object.values(groupsByDay).forEach(group => {
group.forEach(elem => {
let canvas, ctx, particles = [], anim, hovering = false;
let cursorX = 0, cursorY = 0;
function setupCanvas() {
if (canvas) return;
canvas = document.createElement("canvas");
canvas.width = elem.offsetWidth * 1.4;
canvas.height = elem.offsetHeight * 1.4;
canvas.style.position = "absolute";
canvas.style.top = "-20%";
canvas.style.left = "-20%";
canvas.style.pointerEvents = "none";
canvas.style.zIndex = "10";
elem.appendChild(canvas);
ctx = canvas.getContext("2d");
}
elem.addEventListener("mousemove", e => {
const rect = elem.getBoundingClientRect();
cursorX = (e.clientX - rect.left) * 1.4 - (elem.offsetWidth * 0.2);
cursorY = (e.clientY - rect.top) * 1.4 - (elem.offsetHeight * 0.2);
});
function addParticles() {
const cx = cursorX || canvas.width / 2;
const cy = cursorY || canvas.height / 2;
for (let i = 0; i < 4; i++) {
const angle = Math.random() * Math.PI * 2;
const speed = Math.random() * 1.5 + 0.3;
particles.push({
x: cx,
y: cy,
r: Math.random() * 1.3 + 0.2,
alpha: Math.random() * 0.7 + 0.3,
vx: Math.cos(angle) * speed,
vy: Math.sin(angle) * speed,
life: Math.random() * 120 + 60,
decay: Math.random() * 0.015 + 0.008
});
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (hovering) addParticles();
particles.forEach(p => {
ctx.beginPath();
const grad = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, p.r * 3);
grad.addColorStop(0, `rgba(200, 170, 73, ${p.alpha})`);
grad.addColorStop(0.3, `rgba(255, 240, 200, ${p.alpha * 0.8})`);
grad.addColorStop(1, "transparent");
ctx.fillStyle = grad;
ctx.arc(p.x, p.y, p.r * 3, 0, Math.PI * 2);
ctx.fill();
p.x += p.vx;
p.y += p.vy + 0.05;
p.vx *= 0.98;
p.vy *= 0.98;
p.alpha -= p.decay;
p.life--;
});
particles = particles.filter(p => p.life > 0 && p.alpha > 0);
anim = requestAnimationFrame(draw);
}
// HOVER START
elem.addEventListener("mouseenter", () => {
setupCanvas();
hovering = true;
cancelAnimationFrame(anim);
draw();
// WICHTIG: alle Elemente dieses Tages bekommen hover-proxy
group.forEach(p => p.classList.add("hover-proxy"));
});
// HOVER ENDE
elem.addEventListener("mouseleave", () => {
hovering = false;
setTimeout(() => {
if (!hovering) {
cancelAnimationFrame(anim);
particles = [];
if (ctx) ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}, 300);
group.forEach(p => p.classList.remove("hover-proxy"));
});
});
});
});