Fav Komet im Sternenhimmel angezeigt

This commit is contained in:
2026-04-13 08:59:10 +02:00
parent bbb9b4946c
commit 5f981d55a6
2 changed files with 376 additions and 0 deletions
+122
View File
@@ -117,6 +117,25 @@ if ($hasFullAdminAccess && $pdoHeader !== null) {
$pendingApprovals = (int)$stmtPendingUsers->fetchColumn();
}
// Favoriten-Kometen des eingeloggten Users für den Sternenhimmel laden
$favCometsForCanvas = [];
if ($loggedIn && isset($_SESSION['user_id']) && $pdoHeader !== null) {
try {
$stmtFavComets = $pdoHeader->prepare(
'SELECT c.designation_and_name
FROM app_user_comets uc
JOIN comets_mpc c ON c.id = uc.comet_id
WHERE uc.user_id = ? AND uc.is_favorite = 1
ORDER BY c.designation_and_name
LIMIT 8'
);
$stmtFavComets->execute([(int)$_SESSION['user_id']]);
$favCometsForCanvas = $stmtFavComets->fetchAll(PDO::FETCH_COLUMN);
} catch (Throwable $e) {
$favCometsForCanvas = [];
}
}
$menuGroups = [
[
'title' => 'Himmel & Planeten',
@@ -281,6 +300,109 @@ if ($loggedIn && !$hasFullAdminAccess && $pdoHeader !== null) {
})();
</script>
<?php if (!empty($favCometsForCanvas)): ?>
<script>
(function () {
const COMET_NAMES = <?= json_encode(array_values($favCometsForCanvas), JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;
if (!COMET_NAMES.length) return;
const canvas = document.getElementById('starfield');
// Warten bis das Sternfeld-Canvas bereit ist
function initComets() {
if (!canvas.width) { setTimeout(initComets, 100); return; }
const ctx = canvas.getContext('2d');
// Jeden Kometen mit Startposition und Geschwindigkeit initialisieren
const comets = COMET_NAMES.map(function (name, i) {
return makeComet(name, i, COMET_NAMES.length, canvas.width, canvas.height);
});
function makeComet(name, index, total, w, h) {
// Kometen gleichmäßig über die Höhe verteilt, aber mit leichtem Versatz
const seedY = (index + 0.5) / total;
return {
name: name,
x: Math.random() * w,
y: seedY * h * 0.85 + h * 0.05,
// Langsame Bewegung leicht schräg nach rechts-unten
vx: 0.12 + Math.random() * 0.10,
vy: (Math.random() - 0.5) * 0.04,
// Schweif­länge und Coma-Größe
tailLen: 60 + Math.random() * 50,
comaR: 2.5 + Math.random() * 1.5,
// Leichtes Funkeln
phase: Math.random() * Math.PI * 2,
speed: 0.0004 + Math.random() * 0.0003,
};
}
let t = 0;
function drawComets() {
t++;
const w = canvas.width;
const h = canvas.height;
for (const c of comets) {
c.x += c.vx;
c.y += c.vy;
// Wenn rechts raus → links neu eintreten, y leicht variieren
if (c.x - c.tailLen > w) {
c.x = -c.tailLen;
c.y = Math.random() * h * 0.85 + h * 0.05;
}
const alpha = 0.55 + 0.18 * Math.sin(c.phase + t * c.speed * Math.PI * 2);
// --- Schweif (Gradient nach links) ---
const grd = ctx.createLinearGradient(c.x, c.y, c.x - c.tailLen, c.y);
grd.addColorStop(0, `rgba(201,168,76,${(alpha * 0.7).toFixed(3)})`);
grd.addColorStop(0.4, `rgba(240,217,144,${(alpha * 0.25).toFixed(3)})`);
grd.addColorStop(1, 'rgba(201,168,76,0)');
ctx.beginPath();
ctx.moveTo(c.x, c.y);
ctx.lineTo(c.x - c.tailLen, c.y - c.tailLen * 0.06);
ctx.strokeStyle = grd;
ctx.lineWidth = c.comaR * 0.9;
ctx.lineCap = 'round';
ctx.stroke();
// --- Coma (Leuchtkern) ---
const glow = ctx.createRadialGradient(c.x, c.y, 0, c.x, c.y, c.comaR * 3);
glow.addColorStop(0, `rgba(255,245,200,${alpha.toFixed(3)})`);
glow.addColorStop(0.4, `rgba(201,168,76,${(alpha * 0.6).toFixed(3)})`);
glow.addColorStop(1, 'rgba(201,168,76,0)');
ctx.beginPath();
ctx.arc(c.x, c.y, c.comaR * 3, 0, Math.PI * 2);
ctx.fillStyle = glow;
ctx.fill();
// --- Namens-Label ---
ctx.font = '11px sans-serif';
ctx.fillStyle = `rgba(240,217,144,${(alpha * 0.85).toFixed(3)})`;
ctx.textAlign = 'left';
ctx.textBaseline = 'middle';
ctx.fillText(c.name, c.x + c.comaR * 3 + 4, c.y - 8);
}
}
// In den bestehenden Animation-Loop einhängen
const origRAF = window.requestAnimationFrame;
(function loop() {
drawComets();
origRAF(loop);
})();
}
// Kurze Verzögerung damit der Stern-Canvas zuerst initialisiert wird
setTimeout(initComets, 200);
})();
</script>
<?php endif; ?>
<header>
<div class="container">
<div class="header-inner">