MediaWiki:Common.js: Unterschied zwischen den Versionen
Admin (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung |
Admin (Diskussion | Beiträge) Keine Bearbeitungszusammenfassung Markierung: Zurückgesetzt |
||
| Zeile 1.234: | Zeile 1.234: | ||
} | } | ||
})(); | |||
/* ============================================================ | |||
ADOS – Silvester Feuerwerk (ES5, ohne =>) | |||
Aktiv: automatisch zwischen 31.12 und 01.01 | |||
============================================================ */ | |||
(function () { | |||
'use strict'; | |||
// --- Datum prüfen (Europe/Berlin; wir nehmen Local Time des Users) --- | |||
function isNewYears() { | |||
var d = new Date(); | |||
var m = d.getMonth() + 1; // 1-12 | |||
var day = d.getDate(); // 1-31 | |||
// Silvester + Neujahr | |||
return (m === 12 && day === 31) || (m === 1 && day === 1); | |||
} | |||
// Nur an Silvester/Neujahr aktiv | |||
if (!isNewYears()) return; | |||
// Canvas anlegen | |||
function createCanvas() { | |||
var c = document.createElement('canvas'); | |||
c.id = 'ados-fireworks-canvas'; | |||
c.style.position = 'fixed'; | |||
c.style.left = '0'; | |||
c.style.top = '0'; | |||
c.style.width = '100%'; | |||
c.style.height = '100%'; | |||
c.style.pointerEvents = 'none'; | |||
c.style.zIndex = '9999'; | |||
c.style.opacity = '0.85'; | |||
document.body.appendChild(c); | |||
return c; | |||
} | |||
function fitCanvas(c) { | |||
var dpr = window.devicePixelRatio || 1; | |||
c.width = Math.floor(window.innerWidth * dpr); | |||
c.height = Math.floor(window.innerHeight * dpr); | |||
var ctx = c.getContext('2d'); | |||
ctx.setTransform(dpr, 0, 0, dpr, 0, 0); | |||
return ctx; | |||
} | |||
// Einfache Partikel | |||
function rand(min, max) { return min + Math.random() * (max - min); } | |||
function clamp(v, a, b) { return Math.max(a, Math.min(b, v)); } | |||
var canvas, ctx; | |||
var particles = []; | |||
var last = 0; | |||
var running = true; | |||
function spawnBurst(x, y) { | |||
var count = Math.floor(rand(40, 70)); | |||
var i; | |||
for (i = 0; i < count; i++) { | |||
var angle = rand(0, Math.PI * 2); | |||
var speed = rand(2.2, 5.5); | |||
particles.push({ | |||
x: x, | |||
y: y, | |||
vx: Math.cos(angle) * speed, | |||
vy: Math.sin(angle) * speed, | |||
life: rand(700, 1200), | |||
age: 0, | |||
size: rand(1.5, 3.2), | |||
// Farbe: gold/rot/blau/lila | |||
r: Math.floor(rand(120, 255)), | |||
g: Math.floor(rand(80, 220)), | |||
b: Math.floor(rand(120, 255)) | |||
}); | |||
} | |||
} | |||
function tick(ts) { | |||
if (!running) return; | |||
if (!last) last = ts; | |||
var dt = ts - last; | |||
last = ts; | |||
// Hintergrund leicht ausfaden | |||
ctx.fillStyle = 'rgba(0,0,0,0.12)'; | |||
ctx.fillRect(0, 0, window.innerWidth, window.innerHeight); | |||
// Partikel updaten/zeichnen | |||
var i, p; | |||
for (i = particles.length - 1; i >= 0; i--) { | |||
p = particles[i]; | |||
p.age += dt; | |||
if (p.age >= p.life) { | |||
particles.splice(i, 1); | |||
continue; | |||
} | |||
// Physik | |||
p.vy += 0.0028 * dt; // Gravity | |||
p.vx *= Math.pow(0.998, dt); | |||
p.vy *= Math.pow(0.998, dt); | |||
p.x += p.vx * (dt / 16); | |||
p.y += p.vy * (dt / 16); | |||
var t = 1 - (p.age / p.life); | |||
var alpha = clamp(t, 0, 1); | |||
ctx.beginPath(); | |||
ctx.fillStyle = 'rgba(' + p.r + ',' + p.g + ',' + p.b + ',' + alpha + ')'; | |||
ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2, false); | |||
ctx.fill(); | |||
} | |||
requestAnimationFrame(tick); | |||
} | |||
function scheduleBursts() { | |||
// alle ~1.2–2.6s ein Burst an zufälliger Position oben/mitte | |||
function loop() { | |||
if (!running) return; | |||
spawnBurst(rand(80, window.innerWidth - 80), rand(80, window.innerHeight * 0.55)); | |||
setTimeout(loop, Math.floor(rand(1200, 2600))); | |||
} | |||
loop(); | |||
} | |||
function init() { | |||
// nur wenn Seite fertig ist | |||
canvas = createCanvas(); | |||
ctx = fitCanvas(canvas); | |||
// Resize | |||
window.addEventListener('resize', function () { | |||
if (!canvas) return; | |||
ctx = fitCanvas(canvas); | |||
}); | |||
// Start | |||
scheduleBursts(); | |||
requestAnimationFrame(tick); | |||
// Optional: nach 25 Sekunden aus (damit es nicht nervt) | |||
setTimeout(function () { | |||
running = false; | |||
if (canvas && canvas.parentNode) canvas.parentNode.removeChild(canvas); | |||
}, 25000); | |||
} | |||
if (document.readyState === 'loading') { | |||
document.addEventListener('DOMContentLoaded', init, false); | |||
} else { | |||
init(); | |||
} | |||
})(); | })(); | ||