/** * Glossar-Experimente — Gruppe „monsun". * * Registrierung via window.GlossarExperiments[key_slug] = fn(root). * Eigener svgEl-Helper, nur bestehende .ge-*-CSS-Klassen (aus glossar.php). * Keine Libraries. Mobile-/Tap-freundlich. rAF-Loops stoppen bei geschlossenem * Modal über den root.isConnected-Guard. */ (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; }; const deAT = (n) => Number(n).toLocaleString('de-AT'); // ===================================================================== // Experiment: Monsun-Regen — Regen pro Monat in Mumbai (Balkendiagramm) // ===================================================================== function monsunRain(root) { root.innerHTML = `

🌧 Wann fällt der Regen in Indien?

Jeder Balken ist ein Monat in Mumbai (Indien). Schau, wie riesig die Balken von Juni bis September werden. In dieser kurzen Zeit fällt fast der ganze Jahresregen — davon hängt die Reisernte ab.

`; const svg = root.querySelector('.ge-mon-svg'); const sharePill = root.querySelector('#ge-mon-share'); const totalPill = root.querySelector('#ge-mon-total'); const noteEl = root.querySelector('#ge-mon-note'); if (!svg || !sharePill || !totalPill || !noteEl) return; const MONTHS = ['Jän', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez']; // Monsun-Monate (0-basiert): Juni–September const MONSOON = [5, 6, 7, 8]; // Regen pro Monat in mm. // Normal: Mumbai (Colaba) 1981 – 2010, India Meteorological Department. const NORMAL = [1, 0, 1, 0, 16, 506, 769, 472, 356, 82, 9, 3]; // Schwacher Monsun (Dürre-Jahr): Spitzen-Monate stark reduziert. const WEAK = [1, 0, 1, 0, 10, 280, 420, 240, 180, 60, 6, 2]; // Vergleich: Wien fällt Monat für Monat ziemlich gleichmäßig (~60 mm). const WIEN_REF = 60; const NOTES = { normal: 'Regen pro Monat in Mumbai, Normalwerte 1981 – 2010. Quelle: India Meteorological Department (über „Climate of Mumbai"). Ganzes Jahr rund 2.215 mm. Die dünne Linie zeigt Wien: dort fallen jeden Monat etwa 60 mm — ziemlich gleichmäßig.', weak: 'Schwacher Monsun (Dürre-Jahr): geschätzte Werte, in denen die Monsun-Monate viel weniger Regen bringen. So etwas macht Bäuerinnen und Bauern Sorge — der Klimawandel lässt den Monsun unberechenbarer werden. Quelle Normalwerte: India Meteorological Department.' }; // Layout const X0 = 58, X1 = 588; // Plot links/rechts const BASE = 278, TOP = 34; // Baseline / oberer Rand const PLOT_H = BASE - TOP; // Zeichenhöhe const MAX_MM = 800; // feste Skala (Balken schrumpfen sichtbar) const PX_PER_MM = PLOT_H / MAX_MM; const slot = (X1 - X0) / MONTHS.length; const BAR_W = slot * 0.66; const yFor = (mm) => BASE - Math.min(MAX_MM, mm) * PX_PER_MM; // --- Statische Achsen / Gitter --- // Y-Gitterlinien + Beschriftung [0, 200, 400, 600, 800].forEach(mm => { const y = yFor(mm); svgEl('line', { x1: X0, y1: y, x2: X1, y2: y, stroke: '#dae8ec', 'stroke-width': mm === 0 ? '1.6' : '1' }, svg); const t = svgEl('text', { x: X0 - 8, y: y + 4, 'text-anchor': 'end', 'font-size': '11', fill: '#4a4a4a', 'font-weight': '600' }, svg); t.textContent = mm; }); svgEl('text', { x: X0 - 8, y: TOP - 14, 'text-anchor': 'end', 'font-size': '11', fill: '#4a4a4a', 'font-weight': '700' }, svg).textContent = 'mm'; // Monat-Beschriftung + farbige Monsun-Markierung am Boden const barNodes = []; const valNodes = []; MONTHS.forEach((m, i) => { const cx = X0 + slot * i + slot / 2; const isMon = MONSOON.includes(i); // Balken (Höhe wird animiert gesetzt) const bar = svgEl('rect', { x: cx - BAR_W / 2, y: BASE, width: BAR_W, height: 0, rx: 3, fill: isMon ? '#2f7d8a' : '#a9c7cd' }, svg); barNodes.push(bar); // Wert-Label über dem Balken (nur für die großen Monsun-Balken sichtbar) const val = svgEl('text', { x: cx, y: BASE, 'text-anchor': 'middle', 'font-size': '10', 'font-weight': '800', fill: '#1f4e5a', opacity: '0' }, svg); valNodes.push(val); // Monatsname const lbl = svgEl('text', { x: cx, y: BASE + 18, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': isMon ? '800' : '600', fill: isMon ? '#1f4e5a' : '#6a6a6a' }, svg); lbl.textContent = m; }); // „Regenzeit"-Klammer über Jun–Sep const bx0 = X0 + slot * MONSOON[0] + slot * 0.10; const bx1 = X0 + slot * (MONSOON[MONSOON.length - 1] + 1) - slot * 0.10; svgEl('line', { x1: bx0, y1: TOP - 6, x2: bx1, y2: TOP - 6, stroke: '#e8833a', 'stroke-width': '2', 'stroke-linecap': 'round' }, svg); svgEl('text', { x: (bx0 + bx1) / 2, y: TOP - 12, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '800', fill: '#e8833a' }, svg).textContent = 'Regenzeit'; // Wien-Vergleichslinie (dünn, gestrichelt) + Label const wienY = yFor(WIEN_REF); svgEl('line', { x1: X0, y1: wienY, x2: X1, y2: wienY, stroke: '#c85c4a', 'stroke-width': '2', 'stroke-dasharray': '6 4' }, svg); svgEl('text', { x: X1, y: wienY - 6, 'text-anchor': 'end', 'font-size': '10.5', 'font-weight': '800', fill: '#c85c4a' }, svg) .textContent = 'Wien: ~60 mm pro Monat'; // --- Zustand + Animation --- let animId = null; let current = NORMAL; function paint(fromData, toData, scen) { cancelAnimationFrame(animId); const dur = 650; const start = performance.now(); function tick(now) { if (!root.isConnected) { cancelAnimationFrame(animId); return; } const t = Math.min(1, (now - start) / dur); const e = 1 - Math.pow(1 - t, 3); for (let i = 0; i < barNodes.length; i++) { const mm = fromData[i] + (toData[i] - fromData[i]) * e; const y = yFor(mm); barNodes[i].setAttribute('y', y); barNodes[i].setAttribute('height', Math.max(0, BASE - y)); // Wert nur bei den großen Balken (> 100 mm) zeigen if (toData[i] > 100) { valNodes[i].setAttribute('y', y - 5); valNodes[i].textContent = Math.round(mm); valNodes[i].setAttribute('opacity', (t).toFixed(2)); } else { valNodes[i].setAttribute('opacity', '0'); } } if (t < 1) animId = requestAnimationFrame(tick); } animId = requestAnimationFrame(tick); } function setScenario(scen) { const data = scen === 'weak' ? WEAK : NORMAL; const from = current; current = data; const total = data.reduce((a, b) => a + b, 0); const monsoonSum = MONSOON.reduce((a, i) => a + data[i], 0); const share = Math.round((monsoonSum / total) * 100); sharePill.innerHTML = `Juni – September: ${share} % vom Jahresregen`; sharePill.dataset.state = 'warn'; totalPill.innerHTML = `Ganzes Jahr: ${deAT(total)} mm`; totalPill.dataset.state = scen === 'weak' ? 'bad' : 'good'; noteEl.textContent = NOTES[scen]; root.querySelectorAll('[data-scen]').forEach(b => { b.classList.toggle('ge-btn-primary', b.dataset.scen === scen); }); paint(from, data, scen); } root.querySelectorAll('[data-scen]').forEach(b => { b.addEventListener('click', () => setScenario(b.dataset.scen)); }); // Startanimation von 0 hoch current = NORMAL.map(() => 0); setScenario('normal'); } // Registry — Object.assign, damit Ladereihenfolge egal ist. window.GlossarExperiments = Object.assign(window.GlossarExperiments || {}, { 'monsun': monsunRain }); })();