/** * Glossar-Experimente — kleine interaktive Widgets im Detail-Modal. * * Registrierung: window.GlossarExperiments[key_slug] = function (root) { … } * Der Renderer (glossar.php) hängt einen leeren Container ein und ruft die * Funktion mit diesem Container als einzigem Argument auf. Das Widget baut * selbst seinen DOM und bindet seine Events. * * Richtlinien: * - Keine externen Libraries. * - Mobile-/Tap-freundlich: grosse Buttons, keine Hover-Abhängigkeit. * - Zahlen quellenbar, kurze Begründung in der UI sichtbar. */ (function () { 'use strict'; const NS = 'http://www.w3.org/2000/svg'; const svgEl = (tag, attrs, parent) => { const el = document.createElementNS(NS, tag); if (attrs) for (const k in attrs) el.setAttribute(k, attrs[k]); if (parent) parent.appendChild(el); return el; }; // ===================================================================== // Experiment: kWh-Rennen — wie weit kommt man mit 1 Kilowattstunde? // ===================================================================== function kwhRace(root) { root.innerHTML = `

🏁 Das kWh-Rennen

Drei Fahrzeuge starten rechts mit derselben Energie: 1 Kilowattstunde. Wie weit kommen sie nach links?

Quellen: ADAC Stromverbrauchstests E-Auto · Hersteller-Angaben E-Bike Bosch Performance · WLTP Benziner 6 L/100 km × 8,8 kWh/L. Der Benziner verliert rund 70 % der Kraftstoffenergie als Motor-Wärme — deshalb kommt er weniger weit.

`; const svg = root.querySelector('.ge-track'); // Emoji-Fahrzeuge: auf Windows/Chrome schauen 🚴 🚗 🚙 nach links → sie fahren // von rechts nach links, Emojis passen zur Fahrtrichtung ohne Plattform-Trick. const vehicles = [ { label: 'E-Fahrrad', emoji: '🚴', km: 100, color: '#5a8a5e', y: 100 }, { label: 'E-Auto', emoji: '🚗', km: 6.5, color: '#4a7c8a', y: 190 }, { label: 'Benzin-Auto', emoji: '🚙', km: 1.9, color: '#c85c4a', y: 280 } ]; const MAX_KM = 100; const TRACK_L = 50, TRACK_R = 560; const trackLen = TRACK_R - TRACK_L; // Skala oben — Start rechts (0 km), Ziel links (100 km) const axis = svgEl('g', { class: 'ge-axis' }, svg); svgEl('line', { x1: TRACK_L, y1: 52, x2: TRACK_R, y2: 52, stroke: '#1f4e5a', 'stroke-width': '1.2' }, axis); [0, 25, 50, 75, 100].forEach(km => { const x = TRACK_R - (km / MAX_KM) * trackLen; svgEl('line', { x1: x, y1: 48, x2: x, y2: 56, stroke: '#1f4e5a', 'stroke-width': '1' }, axis); const t = svgEl('text', { x, y: 40, 'text-anchor': 'middle', 'font-size': '11', fill: '#4a4a4a', 'font-weight': '600' }, axis); t.textContent = km + ' km'; }); // „Start" Marker ganz rechts const startTxt = svgEl('text', { x: TRACK_R, y: 20, 'text-anchor': 'end', 'font-size': '11', fill: '#1f4e5a', 'font-weight': '700' }, svg); startTxt.textContent = '← Start mit 1 kWh'; // Spuren + Fahrzeuge const nodes = vehicles.map(v => { const g = svgEl('g', { class: 'ge-lane' }, svg); // Label ÜBER der Spur, rechts beim Start const label = svgEl('text', { x: TRACK_R, y: v.y - 22, 'text-anchor': 'end', 'font-size': '12', 'font-weight': '800', fill: v.color }, g); label.textContent = v.label; // Straßenlinie svgEl('line', { x1: TRACK_L, y1: v.y, x2: TRACK_R, y2: v.y, stroke: '#dae8ec', 'stroke-width': '5', 'stroke-linecap': 'round' }, g); // Ziel-Markierung (links vom Start) const xEnd = TRACK_R - (v.km / MAX_KM) * trackLen; svgEl('line', { x1: xEnd, y1: v.y - 16, x2: xEnd, y2: v.y + 16, stroke: v.color, 'stroke-width': '2', 'stroke-dasharray': '3 2', opacity: '.55' }, g); // Emoji-Fahrzeug const icon = svgEl('text', { x: TRACK_R, y: v.y + 8, 'text-anchor': 'middle', 'font-size': '30' }, g); icon.textContent = v.emoji; // Ergebnis-Label LINKS vom Ziel (in Fahrtrichtung weiter) const result = svgEl('text', { x: xEnd - 10, y: v.y + 4, 'text-anchor': 'end', 'font-size': '12', 'font-weight': '800', fill: v.color, opacity: '0' }, g); result.textContent = v.km.toFixed(1).replace('.', ',') + ' km'; return { v, icon, result, xStart: TRACK_R, xEnd }; }); // Animation let animId = null; function setX(n, x) { n.icon.setAttribute('x', x); } function animate() { cancelAnimationFrame(animId); const dur = 6500; // ms — bewusst langsam const start = performance.now(); nodes.forEach(n => { setX(n, n.xStart); n.result.setAttribute('opacity', '0'); }); function tick(now) { const t = Math.min(1, (now - start) / dur); const e = 1 - Math.pow(1 - t, 3); nodes.forEach(n => { const x = n.xStart + (n.xEnd - n.xStart) * e; setX(n, x); if (t > 0.96) n.result.setAttribute('opacity', '1'); }); if (t < 1) animId = requestAnimationFrame(tick); } animId = requestAnimationFrame(tick); } function reset() { cancelAnimationFrame(animId); nodes.forEach(n => { setX(n, n.xStart); n.result.setAttribute('opacity', '0'); }); } root.querySelector('[data-act="start"]').addEventListener('click', animate); root.querySelector('[data-act="reset"]').addEventListener('click', reset); } // ===================================================================== // Experiment: ppm-Raster — 1 Teilchen von 1.000.000 findet man kaum // ===================================================================== function ppmGrid(root) { root.innerHTML = `

🔍 Finde das eine Teilchen

Unten siehst du ein Gitter mit 10.000 Punkten. Ein einziger Punkt ist rot — das entspräche 100 ppm (echte 1 ppm wäre nochmal 100× feiner). Versuche, ihn zu finden und zu tippen!

Bei der aktuellen CO₂-Konzentration von 422 ppm sind 422 von 1.000.000 Luftteilchen CO₂. Das klingt winzig — reicht aber, um die Erde messbar zu erwärmen. Quelle: NOAA Mauna Loa (2024).

`; const grid = root.querySelector('#ge-ppm'); const msg = root.querySelector('.ge-ppm-msg'); const COLS = 100, ROWS = 100; let special = Math.floor(Math.random() * COLS * ROWS); let found = false; function render() { grid.innerHTML = ''; grid.style.gridTemplateColumns = `repeat(${COLS}, 1fr)`; for (let i = 0; i < COLS * ROWS; i++) { const cell = document.createElement('span'); if (i === special) cell.className = 'ge-ppm-special'; grid.appendChild(cell); } msg.textContent = ''; msg.classList.remove('show', 'miss'); found = false; } function highlight() { const el = grid.children[special]; if (!el) return; el.classList.add('ge-ppm-flash'); setTimeout(() => el.classList.remove('ge-ppm-flash'), 1800); } function newOne() { special = Math.floor(Math.random() * COLS * ROWS); render(); } function onHit(cell) { if (found) return; found = true; cell.classList.add('ge-ppm-hit'); msg.textContent = '🎉 Getroffen! Das war 1 von 10.000 Punkten.'; msg.classList.remove('miss'); msg.classList.add('show'); } function onMiss() { if (found) return; msg.textContent = 'Daneben — probier "Tipp zeigen" für eine kurze Hilfe.'; msg.classList.remove('show'); msg.classList.add('show', 'miss'); } // Click-Handler delegiert auf das Grid (funktioniert auch bei 4-px-Zellen) grid.addEventListener('click', ev => { const target = ev.target; if (target === grid) return; if (target.classList && target.classList.contains('ge-ppm-special')) onHit(target); else onMiss(); }); render(); root.querySelector('[data-act="highlight"]').addEventListener('click', highlight); root.querySelector('[data-act="new"]').addEventListener('click', newOne); } // ===================================================================== // Experiment: Albedo-Slider — Oberfläche wechseln, Reflexion beobachten // ===================================================================== function albedoSlider(root) { const surfaces = [ { key: 'snow', label: 'Frischer Schnee', albedo: 0.85, color: '#ffffff', border: '#b5c9cf' }, { key: 'desert', label: 'Sand-Wüste', albedo: 0.35, color: '#e8d5b5', border: '#c4a97a' }, { key: 'forest', label: 'Wald', albedo: 0.12, color: '#3a6b3e', border: '#2a5030' }, { key: 'ocean', label: 'Ozean', albedo: 0.06, color: '#1f4e5a', border: '#0f2f3a' }, { key: 'asphalt', label: 'Asphalt', albedo: 0.05, color: '#2a2a2a', border: '#1a1a1a' } ]; root.innerHTML = `

☀ Welche Oberfläche reflektiert wie viel?

Wähle eine Oberfläche. Die Pfeile zeigen, wie viel Sonnenlicht zurückgeworfen wird.

${surfaces.map((s, i) => ` `).join('')}
Albedo: 0,85
Reflektiert: 85 %
Absorbiert: 15 %

Darum erwärmt sich die Arktis 4-mal schneller als die Erde insgesamt: Schmilzt Eis, kommt darunter dunkler Ozean zum Vorschein, der viel mehr Sonnenenergie aufnimmt. Quelle: Rantanen et al. 2022.

`; const svg = root.querySelector('.ge-albedo-svg'); const valEl = root.querySelector('#ge-alb-val'); const reflEl = root.querySelector('#ge-alb-refl'); const absEl = root.querySelector('#ge-alb-abs'); // Statischer Aufbau: Himmel + Sonne + Bodenrechteck svgEl('rect', { x: 0, y: 0, width: 600, height: 210, fill: '#eff5f6' }, svg); svgEl('circle', { cx: 90, cy: 70, r: 30, fill: '#f4c94e' }, svg); const surfaceRect = svgEl('rect', { x: 0, y: 210, width: 600, height: 110, fill: '#ffffff', stroke: '#b5c9cf', 'stroke-width': '1.5' }, svg); // Einfallender Lichtstrahl (Sonne → Boden) svgEl('line', { x1: 110, y1: 100, x2: 300, y2: 210, stroke: '#e8833a', 'stroke-width': '3', 'stroke-linecap': 'round' }, svg); svgEl('polygon', { points: '295,205 306,208 300,215', fill: '#e8833a' }, svg); // Reflexions-Pfeile (dynamisch nach Albedo) const reflG = svgEl('g', { class: 'ge-albedo-refl' }, svg); function setSurface(key) { const s = surfaces.find(x => x.key === key) || surfaces[0]; surfaceRect.setAttribute('fill', s.color); surfaceRect.setAttribute('stroke', s.border); // Anzahl reflektierter Pfeile proportional zur Albedo (1 bis 9 Pfeile) reflG.innerHTML = ''; const nArrows = Math.max(1, Math.round(s.albedo * 10)); for (let i = 0; i < nArrows; i++) { const angle = -60 + i * (120 / Math.max(1, nArrows - 1)); const rad = angle * Math.PI / 180; const startX = 300, startY = 210; const len = 120; const endX = startX + Math.cos(rad) * len; const endY = startY - Math.sin(Math.abs(rad) * Math.PI / 180 + 0.3) * Math.abs(len * Math.cos(rad) / 90) - 60; // Simpler: Linien gleichmäßig nach oben gefächert const e2x = 300 + Math.sin(rad) * len; const e2y = 210 - Math.cos(rad) * len; svgEl('line', { x1: startX, y1: startY, x2: e2x, y2: e2y, stroke: '#f4c94e', 'stroke-width': '2', 'stroke-linecap': 'round', opacity: '0.85' }, reflG); } valEl.textContent = s.albedo.toFixed(2).replace('.', ','); reflEl.textContent = Math.round(s.albedo * 100) + ' %'; absEl.textContent = Math.round((1 - s.albedo) * 100) + ' %'; root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => { b.classList.toggle('ge-btn-primary', b.dataset.key === s.key); }); } root.querySelectorAll('.ge-albedo-choice .ge-btn').forEach(b => { b.addEventListener('click', () => setSurface(b.dataset.key)); }); setSurface('snow'); } // ===================================================================== // Experiment: CO₂-Fußabdruck-Rechner — schneller Alltags-Schätzer // ===================================================================== function footprintCalc(root) { root.innerHTML = `

🧮 Schätze deinen CO₂-Fußabdruck

Einfache Auswahl pro Bereich. Das Ergebnis ist eine Richtgröße — kein genauer Wert.

🏠 Wohnen
🚗 Verkehr
🍽 Ernährung
🛒 Konsum
Dein geschätzter Fußabdruck:
7,6 t CO₂ / Jahr
0 tWelt-Ø 4,7AT-Ø 7,710 t
Klimaneutral-Ziel: unter 1 t — Welt-Durchschnitt: 4,7 t — Österreich: 7,7 t.

Die Anteile decken sich mit den Haupt-Kategorien im Klimaschutzbericht 2024 des Umweltbundesamts Österreich. Details pro Kategorie unter CO₂-Fußabdruck.

`; const totals = { home: 2.0, car: 1.8, food: 1.8, shop: 2.0 }; function update() { const sum = Object.values(totals).reduce((a, b) => a + b, 0); root.querySelector('.ge-calc-total').textContent = sum.toFixed(1).replace('.', ',') + ' t CO₂ / Jahr'; const pct = Math.min(100, (sum / 10) * 100); root.querySelector('.ge-calc-fill').style.width = pct + '%'; } root.querySelectorAll('.ge-calc-opts').forEach(group => { const key = group.dataset.key; group.querySelectorAll('.ge-btn').forEach(btn => { btn.addEventListener('click', () => { group.querySelectorAll('.ge-btn').forEach(b => b.classList.remove('ge-btn-primary')); btn.classList.add('ge-btn-primary'); totals[key] = parseFloat(btn.dataset.val); update(); }); }); }); update(); } // Registry — Key entspricht key_slug aus DB window.GlossarExperiments = { 'kilowattstunde': kwhRace, 'ppm': ppmGrid, 'albedo': albedoSlider, 'co2-fussabdruck': footprintCalc }; })();