Glossar: 4 erklärende Widgets + 2 Einträge anschaulicher
Widgets: Ernährungspyramide (US-1992 vs DACH-2024 vs Denkfehler), Kakao-Bohne (Schoko-Fließband + Mischverhältnis→Sorte/kaputte Masse), Klimazone (Bänder Äquator→Pol mit Beispielpflanzen), Monsun (Monatsregen-Balkendiagramm Mumbai + Wien-Vergleich, Quelle IMD). Texte: off-season-import (Winter-Erdbeere ~10× CO₂, Schiff vs Flug) + lebensmittelverschwendung (70 kg = ~6 Wochen Essen; 700 Mio. Hungernde) — greifbare Vergleiche. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* Glossar-Experimente — Klimazonen.
|
||||
*
|
||||
* Registrierung: window.GlossarExperiments['klimazone'] = function (root) { … }
|
||||
* Der Renderer (glossar.php) hängt einen leeren Container ein und ruft die
|
||||
* Funktion mit diesem Container als einzigem Argument auf.
|
||||
*
|
||||
* Nur bestehende .ge-*-Klassen aus glossar.php verwenden, kein neues CSS.
|
||||
*/
|
||||
|
||||
(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: Klimazonen der Erde — Querschnitt Äquator → Pol
|
||||
// Bänder anklicken → Temperatur, Regen und was dort wächst.
|
||||
// =====================================================================
|
||||
function climateZones(root) {
|
||||
// Bänder von OBEN (Pol, kalt) nach UNTEN (Äquator, heiß).
|
||||
// y-Werte passen zu viewBox 0 0 600 340.
|
||||
const zones = [
|
||||
{
|
||||
key: 'polar',
|
||||
name: 'Polargebiete',
|
||||
where: 'Arktis · Antarktis',
|
||||
temp: '−30 – 0 °C',
|
||||
rain: 'sehr wenig, meist Schnee',
|
||||
grows: 'kein Ackerbau — zu kalt',
|
||||
emoji: '🧊',
|
||||
color: '#dbe9ee', text: '#2a4a55', border: '#9fbcc6',
|
||||
state: 'now'
|
||||
},
|
||||
{
|
||||
key: 'boreal',
|
||||
name: 'Kalte Zone (Nadelwald)',
|
||||
where: 'Skandinavien · Kanada',
|
||||
temp: '0 – 5 °C im Jahr',
|
||||
rain: 'mittel, lange kalte Winter',
|
||||
grows: 'Nadelwald, Beeren — kaum Ackerbau',
|
||||
emoji: '🌲',
|
||||
color: '#5a8a8f', text: '#ffffff', border: '#3d6b70',
|
||||
state: 'now'
|
||||
},
|
||||
{
|
||||
key: 'temperate',
|
||||
name: 'Gemäßigte Zone',
|
||||
where: 'Österreich · Mitteleuropa',
|
||||
temp: '8 – 12 °C im Jahr',
|
||||
rain: '600 – 1.000 mm, 4 Jahreszeiten',
|
||||
grows: 'Äpfel, Getreide, Erdäpfel',
|
||||
emoji: '🍎',
|
||||
color: '#4a7c4e', text: '#ffffff', border: '#356139',
|
||||
state: 'good',
|
||||
home: true
|
||||
},
|
||||
{
|
||||
key: 'subtropic',
|
||||
name: 'Subtropen',
|
||||
where: 'Mittelmeer · Kalifornien',
|
||||
temp: '15 – 22 °C im Jahr',
|
||||
rain: 'trockene heiße Sommer',
|
||||
grows: 'Oliven, Zitrusfrüchte, Mandeln',
|
||||
emoji: '🍊',
|
||||
color: '#e8c547', text: '#4a3d0a', border: '#c9a516',
|
||||
state: 'warn'
|
||||
},
|
||||
{
|
||||
key: 'tropic',
|
||||
name: 'Tropen (Äquator)',
|
||||
where: 'heiß und feucht',
|
||||
temp: '24 – 28 °C, immer warm',
|
||||
rain: '1.500 – 3.000 mm, sehr viel Regen',
|
||||
grows: 'Kakao, Banane, Kaffee, Reis',
|
||||
emoji: '🍌',
|
||||
color: '#2e7d4f', text: '#ffffff', border: '#1f5a38',
|
||||
state: 'warn'
|
||||
}
|
||||
];
|
||||
|
||||
root.innerHTML = `
|
||||
<div class="ge-wrap">
|
||||
<div class="ge-head">
|
||||
<h3>🌍 Die Klimazonen der Erde</h3>
|
||||
<p>Von unten (Äquator, viel Sonne) nach oben (Pol, wenig Sonne) wird es kühler. Tippe auf ein Band und schau, was dort wächst.</p>
|
||||
</div>
|
||||
<svg class="ge-gh-svg" viewBox="0 0 600 340" preserveAspectRatio="xMidYMid meet" role="group" aria-label="Klimazonen von Äquator bis Pol"></svg>
|
||||
<div class="ge-gh-result">
|
||||
<div class="ge-gh-pill" id="ge-kz-info" data-state="good">Tippe auf ein Band …</div>
|
||||
<div class="ge-gh-pill" id="ge-kz-key" data-state="now">Wo etwas wächst, hängt von Wärme und Regen ab.</div>
|
||||
</div>
|
||||
<p class="ge-note">Einteilung nach den Klimazonen der Köppen-Geiger-Klassifikation; Temperatur- und Niederschlagsbereiche sind grobe kindgerechte Richtwerte. Quelle: Klimadiagramme & Köppen-Geiger-Klassifikation.</p>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const svg = root.querySelector('.ge-gh-svg');
|
||||
const info = root.querySelector('#ge-kz-info');
|
||||
const keyPill = root.querySelector('#ge-kz-key');
|
||||
if (!svg || !info || !keyPill) return;
|
||||
|
||||
const BAND_X = 92;
|
||||
const BAND_W = 466;
|
||||
const BAND_H = 54;
|
||||
const TOP = 26;
|
||||
|
||||
// Linke Achse: Pol oben → Äquator unten, mit Sonnen-Symbol.
|
||||
const axisTop = TOP;
|
||||
const axisBot = TOP + zones.length * BAND_H;
|
||||
svgEl('line', { x1: 60, y1: axisTop, x2: 60, y2: axisBot, stroke: '#4a4a4a', 'stroke-width': '1.5' }, svg);
|
||||
// Pfeilspitzen (oben = kalt, unten = warm)
|
||||
svgEl('polygon', { points: `60,${axisTop - 8} 55,${axisTop + 2} 65,${axisTop + 2}`, fill: '#4a4a4a' }, svg);
|
||||
svgEl('polygon', { points: `60,${axisBot + 8} 55,${axisBot - 2} 65,${axisBot - 2}`, fill: '#4a4a4a' }, svg);
|
||||
const polTxt = svgEl('text', { x: 44, y: axisTop + 6, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '800', fill: '#2a4a55', transform: `rotate(-90, 44, ${axisTop + 40})` }, svg);
|
||||
polTxt.textContent = 'Pol ❄';
|
||||
const aeqTxt = svgEl('text', { x: 44, y: axisBot - 4, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '800', fill: '#2e7d4f', transform: `rotate(-90, 44, ${axisBot - 40})` }, svg);
|
||||
aeqTxt.textContent = 'Äquator ☀';
|
||||
|
||||
const nodes = [];
|
||||
let current = null;
|
||||
|
||||
zones.forEach((z, i) => {
|
||||
const y = TOP + i * BAND_H;
|
||||
const g = svgEl('g', { class: 'ge-kz-band', style: 'cursor:pointer', tabindex: '0', role: 'button', 'aria-label': z.name }, svg);
|
||||
const rect = svgEl('rect', {
|
||||
x: BAND_X, y: y + 2, width: BAND_W, height: BAND_H - 4, rx: 8,
|
||||
fill: z.color, stroke: z.border, 'stroke-width': '1.5'
|
||||
}, g);
|
||||
// Emoji links im Band
|
||||
svgEl('text', { x: BAND_X + 26, y: y + BAND_H / 2 + 9, 'text-anchor': 'middle', 'font-size': '26' }, g)
|
||||
.textContent = z.emoji;
|
||||
// Zonenname
|
||||
const name = svgEl('text', { x: BAND_X + 52, y: y + BAND_H / 2 - 2, 'font-size': '14', 'font-weight': '800', fill: z.text }, g);
|
||||
name.textContent = z.name;
|
||||
// Wo (klein darunter)
|
||||
const sub = svgEl('text', { x: BAND_X + 52, y: y + BAND_H / 2 + 15, 'font-size': '10.5', 'font-weight': '600', fill: z.text, opacity: '0.9' }, g);
|
||||
sub.textContent = z.where;
|
||||
// „Hier ist Österreich"-Marker
|
||||
if (z.home) {
|
||||
const marker = svgEl('g', {}, g);
|
||||
svgEl('rect', { x: BAND_X + BAND_W - 118, y: y + BAND_H / 2 - 13, width: 112, height: 24, rx: 12, fill: '#ffffff', stroke: '#c85c4a', 'stroke-width': '1.5' }, marker);
|
||||
svgEl('text', { x: BAND_X + BAND_W - 62, y: y + BAND_H / 2 + 3, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '800', fill: '#c85c4a' }, marker)
|
||||
.textContent = '📍 Österreich';
|
||||
}
|
||||
nodes.push({ z, rect });
|
||||
|
||||
const activate = () => select(i);
|
||||
g.addEventListener('click', activate);
|
||||
g.addEventListener('keydown', (ev) => {
|
||||
if (ev.key === 'Enter' || ev.key === ' ') { ev.preventDefault(); activate(); }
|
||||
});
|
||||
});
|
||||
|
||||
function select(i) {
|
||||
const z = zones[i];
|
||||
current = i;
|
||||
// Auswahl-Rahmen setzen
|
||||
nodes.forEach((n, j) => {
|
||||
n.rect.setAttribute('stroke', j === i ? '#1f4e5a' : n.z.border);
|
||||
n.rect.setAttribute('stroke-width', j === i ? '3.5' : '1.5');
|
||||
});
|
||||
info.dataset.state = z.state;
|
||||
info.innerHTML =
|
||||
`<strong>${z.name}</strong> · ${z.where}` +
|
||||
`<br>🌡 ${z.temp}` +
|
||||
`<br>💧 Regen: ${z.rain}` +
|
||||
`<br>🌱 Wächst: <strong>${z.grows}</strong>`;
|
||||
|
||||
// Kernerkenntnis dynamisch auf die gewählte Zone beziehen
|
||||
let msg;
|
||||
if (z.key === 'tropic') {
|
||||
msg = 'In den Tropen ist es heiß und feucht — nur hier wächst Kakao für Schokolade.';
|
||||
} else if (z.key === 'temperate') {
|
||||
msg = 'Bei uns in Österreich ist es mild mit Regen — perfekt für Äpfel und Getreide, aber zu kühl für Kakao.';
|
||||
} else if (z.key === 'polar' || z.key === 'boreal') {
|
||||
msg = 'Zu kalt und zu wenig Sonne: hier gibt es kaum oder gar keinen Ackerbau.';
|
||||
} else {
|
||||
msg = 'Heiße, trockene Sommer mögen Oliven und Zitrusfrüchte — bei uns wäre es dafür zu kühl.';
|
||||
}
|
||||
keyPill.dataset.state = 'now';
|
||||
keyPill.innerHTML = `<strong>Merke:</strong> ${msg}`;
|
||||
}
|
||||
|
||||
// Startzustand: gemäßigte Zone (Österreich) vorgewählt
|
||||
select(2);
|
||||
}
|
||||
|
||||
// Registry — Object.assign, damit die Ladereihenfolge egal ist.
|
||||
window.GlossarExperiments = Object.assign(window.GlossarExperiments || {}, {
|
||||
'klimazone': climateZones
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user