f8e77910ea
Bilder (Flat-Scandinavian, gpt-image-1) für alle 51 neuen Begriffe; 12 Widgets in neu1.js (strommix, eisschild, klimabilanz, megawattstunde, niederschlag, fruchtfolge) und neu2.js (halbschatten, blockabfertigung, grundfreiheiten, synergie, aufenthaltsdauer, grundwasser). image_path + module-Mappings, key_slug-basiert. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
558 lines
26 KiB
JavaScript
558 lines
26 KiB
JavaScript
/**
|
||
* Glossar-Experimente „neu1" — Energie, Klima, Boden.
|
||
*
|
||
* Registrierung wie in glossar-experiments.js:
|
||
* window.GlossarExperiments[key_slug] = function (root) { … }
|
||
* Der Renderer (glossar.php) übergibt einen leeren Container; das Widget baut
|
||
* seinen DOM selbst und bindet seine Events. Styles: nur .ge-* aus glossar.php.
|
||
*
|
||
* Richtlinien:
|
||
* - Keine externen Libraries, Vanilla JS + SVG.
|
||
* - Mobile-/Tap-freundlich, keine Hover-Abhängigkeit.
|
||
* - Zahlen mit kurzer Quellenangabe in der .ge-note.
|
||
* - Rechenzeichen · und : (nie ×/÷), deutsche Zahlen via toLocaleString.
|
||
*/
|
||
|
||
(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 deInt = (n) => Math.round(n).toLocaleString('de-AT');
|
||
const deNum = (n, dec) => n.toFixed(dec === undefined ? 1 : dec).replace('.', ',');
|
||
|
||
// =====================================================================
|
||
// Experiment: strommix — 5 Regler, CO₂-Ampel für den Strom-Mix
|
||
// =====================================================================
|
||
function strommix(root) {
|
||
// Lebenszyklus-CO₂ je kWh (Median IPCC AR5), gerundet in g/kWh
|
||
const sources = [
|
||
{ key: 'wasser', label: '💧 Wasserkraft', co2: 24, color: '#4a7c8a', val: 40 },
|
||
{ key: 'wind', label: '🌬️ Windkraft', co2: 11, color: '#5a8a5e', val: 25 },
|
||
{ key: 'sonne', label: '☀️ Sonne (PV)', co2: 48, color: '#e8c547', val: 15 },
|
||
{ key: 'gas', label: '🔥 Erdgas', co2: 490, color: '#e8833a', val: 15 },
|
||
{ key: 'kohle', label: '🪨 Kohle', co2: 820, color: '#4a4a4a', val: 5 }
|
||
];
|
||
|
||
root.innerHTML = `
|
||
<div class="ge-wrap">
|
||
<div class="ge-head">
|
||
<h3>🔌 Baue deinen Strom-Mix</h3>
|
||
<p>Stell mit den Reglern ein, woher der Strom kommt. Die Anteile werden immer auf <strong>100 %</strong> gerechnet. Beobachte die CO₂-Ampel!</p>
|
||
</div>
|
||
<svg class="ge-gh-svg" viewBox="0 0 600 70" preserveAspectRatio="none" aria-hidden="true"></svg>
|
||
<div class="ge-gh-slider" id="sm-sliders"></div>
|
||
<div class="ge-gh-result">
|
||
<div class="ge-gh-pill">CO₂ je Kilowattstunde: <strong id="sm-co2">–</strong> g</div>
|
||
<div class="ge-gh-pill" id="sm-verdict">–</div>
|
||
</div>
|
||
<div class="ge-calc-bar"><div class="ge-calc-fill" id="sm-bar" style="width:0%"></div></div>
|
||
<div class="ge-calc-scale"><span>0 g</span><span>sauber</span><span>schmutzig</span><span>820 g</span></div>
|
||
<p class="ge-note">CO₂-Werte je kWh über den ganzen Lebensweg (Median): Wind 11 g · Wasser 24 g · Sonne 48 g · Erdgas 490 g · Kohle 820 g. Quelle: IPCC AR5 (2014), Anhang III. Viel Wasser, Wind und Sonne = sehr wenig CO₂.</p>
|
||
</div>
|
||
`;
|
||
|
||
const bar = svgEl('g', {}, root.querySelector('.ge-gh-svg'));
|
||
const co2Out = root.querySelector('#sm-co2');
|
||
const verdict = root.querySelector('#sm-verdict');
|
||
const barFill = root.querySelector('#sm-bar');
|
||
const sliderBox = root.querySelector('#sm-sliders');
|
||
if (!sliderBox) return;
|
||
|
||
const shareEls = {};
|
||
sources.forEach(s => {
|
||
const row = document.createElement('div');
|
||
row.style.marginBottom = '.55rem';
|
||
row.innerHTML = `
|
||
<label for="sm-${s.key}" style="display:flex;justify-content:space-between;">
|
||
<span>${s.label}</span><strong id="sm-share-${s.key}">0 %</strong>
|
||
</label>
|
||
<input id="sm-${s.key}" type="range" min="0" max="100" step="5" value="${s.val}">
|
||
`;
|
||
sliderBox.appendChild(row);
|
||
shareEls[s.key] = row.querySelector('#sm-share-' + s.key);
|
||
const inp = row.querySelector('input');
|
||
inp.addEventListener('input', () => { s.val = +inp.value; update(); });
|
||
});
|
||
|
||
function update() {
|
||
const sum = sources.reduce((a, s) => a + s.val, 0) || 1;
|
||
// Gestapelter Farbbalken + Anteil-Texte
|
||
bar.innerHTML = '';
|
||
let x = 0;
|
||
let co2mix = 0;
|
||
sources.forEach(s => {
|
||
const share = s.val / sum;
|
||
co2mix += share * s.co2;
|
||
const w = share * 600;
|
||
if (w > 0.5) svgEl('rect', { x, y: 0, width: w, height: 70, fill: s.color }, bar);
|
||
x += w;
|
||
if (shareEls[s.key]) shareEls[s.key].textContent = Math.round(share * 100) + ' %';
|
||
});
|
||
|
||
co2Out.textContent = deInt(co2mix);
|
||
barFill.style.width = Math.min(100, (co2mix / 820) * 100) + '%';
|
||
|
||
let state, txt;
|
||
if (co2mix < 80) { state = 'good'; txt = '🟢 sehr sauber'; }
|
||
else if (co2mix < 250) { state = 'now'; txt = '🟡 noch ok'; }
|
||
else if (co2mix < 500) { state = 'warn'; txt = '🟠 zu viel CO₂'; }
|
||
else { state = 'bad'; txt = '🔴 sehr schmutzig'; }
|
||
barFill.style.background = state === 'good' ? '#5a8a5e' : state === 'now' ? '#4a7c8a' : state === 'warn' ? '#e8833a' : '#c85c4a';
|
||
verdict.textContent = txt;
|
||
verdict.dataset.state = state;
|
||
}
|
||
update();
|
||
}
|
||
|
||
// =====================================================================
|
||
// Experiment: eisschild — Temperatur → Eisschmelze → Meeresspiegel
|
||
// =====================================================================
|
||
function eisschild(root) {
|
||
root.innerHTML = `
|
||
<div class="ge-wrap">
|
||
<div class="ge-head">
|
||
<h3>🧊 Wenn das Eis schmilzt</h3>
|
||
<p>Schiebe den Regler und mach es wärmer. Das Eis auf Grönland und der Antarktis schmilzt — und das Meer steigt. Was passiert mit der Küste?</p>
|
||
</div>
|
||
<svg class="ge-gh-svg" viewBox="0 0 600 320" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
|
||
<div class="ge-gh-slider">
|
||
<label for="es-range">Erwärmung: <strong id="es-temp">+0,0 °C</strong></label>
|
||
<input id="es-range" type="range" min="0" max="50" value="0" step="1">
|
||
<div class="ge-gh-markers"><span>0</span><span>+1,5</span><span>+3</span><span>+5 °C</span></div>
|
||
</div>
|
||
<div class="ge-gh-result">
|
||
<div class="ge-gh-pill">Meeresspiegel: <strong id="es-sea">+0,0 m</strong></div>
|
||
<div class="ge-gh-pill" id="es-verdict">–</div>
|
||
</div>
|
||
<p class="ge-note">Vollständig geschmolzen hebt Grönland-Eis den Meeresspiegel um rund 7 m, das Antarktis-Eis um rund 58 m. Das dauert sehr lange, doch schon ab etwa +1,5 °C beginnt Grönland zu kippen. Quelle: AWI (Alfred-Wegener-Institut).</p>
|
||
</div>
|
||
`;
|
||
const svg = root.querySelector('.ge-gh-svg');
|
||
const rng = root.querySelector('#es-range');
|
||
const tempOut = root.querySelector('#es-temp');
|
||
const seaOut = root.querySelector('#es-sea');
|
||
const verdict = root.querySelector('#es-verdict');
|
||
if (!svg || !rng) return;
|
||
|
||
// Himmel + Sonne
|
||
svgEl('rect', { x: 0, y: 0, width: 600, height: 320, fill: '#dce9ee' }, svg);
|
||
const sun = svgEl('circle', { cx: 520, cy: 55, r: 30, fill: '#f4c94e' }, svg);
|
||
|
||
// Zwei Eisschilde als Blöcke, die von oben schrumpfen (y wächst, height sinkt)
|
||
// Grönland links, Antarktis Mitte-rechts. Basis auf Landsockel bei y=210.
|
||
const landY = 210;
|
||
svgEl('rect', { x: 40, y: landY, width: 150, height: 24, fill: '#6b8e6f' }, svg); // Grönland-Land
|
||
svgEl('rect', { x: 230, y: landY, width: 210, height: 24, fill: '#6b8e6f' }, svg); // Antarktis-Land
|
||
const groenIce = svgEl('rect', { x: 45, y: 90, width: 140, height: 120, fill: '#f4f8fb', stroke: '#b5c9cf', 'stroke-width': '1.5' }, svg);
|
||
const antaIce = svgEl('rect', { x: 235, y: 60, width: 200, height: 150, fill: '#f4f8fb', stroke: '#b5c9cf', 'stroke-width': '1.5' }, svg);
|
||
svgEl('text', { x: 115, y: 82, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = 'Grönland';
|
||
svgEl('text', { x: 335, y: 52, 'text-anchor': 'middle', 'font-size': '11', 'font-weight': '700', fill: '#1f4e5a' }, svg).textContent = 'Antarktis';
|
||
|
||
// Küste rechts mit Häusern
|
||
svgEl('rect', { x: 470, y: landY, width: 130, height: 90, fill: '#c4a97a' }, svg);
|
||
const houses = [
|
||
{ x: 486, base: 200, h: 26 },
|
||
{ x: 522, base: 195, h: 32 },
|
||
{ x: 560, base: 190, h: 38 }
|
||
].map(hd => {
|
||
const g = svgEl('g', {}, svg);
|
||
svgEl('rect', { x: hd.x, y: hd.base - hd.h, width: 26, height: hd.h, fill: '#e8e4d8', stroke: '#1f4e5a', 'stroke-width': '1' }, g);
|
||
svgEl('polygon', { points: `${hd.x - 3},${hd.base - hd.h} ${hd.x + 13},${hd.base - hd.h - 12} ${hd.x + 29},${hd.base - hd.h}`, fill: '#c85c4a' }, g);
|
||
return { g, floodY: hd.base - hd.h + 6 };
|
||
});
|
||
|
||
// Wasser (steigt) ganz vorne
|
||
const seaMaxTop = 120, seaBottom = 320;
|
||
const sea = svgEl('rect', { x: 0, y: seaBottom - 40, width: 600, height: 40, fill: '#4a7c8a', opacity: '0.82' }, svg);
|
||
|
||
function update() {
|
||
const temp = +rng.value / 10; // 0..5 °C
|
||
tempOut.textContent = '+' + deNum(temp, 1) + ' °C';
|
||
|
||
// Schmelzanteile (vereinfachte Schwellen, langfristig)
|
||
const groenFrac = Math.max(0, Math.min(1, (temp - 1.5) / 3.5));
|
||
const antaFrac = Math.max(0, Math.min(1, (temp - 2.0) / 6.0));
|
||
const seaM = groenFrac * 7 + antaFrac * 58; // in Metern (langfristiges Maximum)
|
||
|
||
// Eisblöcke schrumpfen von oben
|
||
const gFullY = 90, gFullH = 120;
|
||
const gH = gFullH * (1 - groenFrac);
|
||
groenIce.setAttribute('y', gFullY + (gFullH - gH));
|
||
groenIce.setAttribute('height', Math.max(0, gH));
|
||
const aFullY = 60, aFullH = 150;
|
||
const aH = aFullH * (1 - antaFrac);
|
||
antaIce.setAttribute('y', aFullY + (aFullH - aH));
|
||
antaIce.setAttribute('height', Math.max(0, aH));
|
||
|
||
// Wasserstand: 0 m → y=280 (Höhe 40), 65 m → y=seaMaxTop
|
||
const frac = Math.min(1, seaM / 65);
|
||
const top = 280 - frac * (280 - seaMaxTop);
|
||
sea.setAttribute('y', top);
|
||
sea.setAttribute('height', seaBottom - top);
|
||
|
||
seaOut.textContent = '+' + deNum(seaM, seaM < 10 ? 1 : 0) + ' m';
|
||
|
||
houses.forEach(h => {
|
||
const flooded = top <= h.floodY;
|
||
h.g.setAttribute('opacity', flooded ? '0.35' : '1');
|
||
});
|
||
|
||
let state, txt;
|
||
if (temp < 1.5) { state = 'good'; txt = '🟢 Eis bleibt stabil'; }
|
||
else if (temp < 2.5) { state = 'now'; txt = '🟡 Grönland kippt'; }
|
||
else if (temp < 4) { state = 'warn'; txt = '🟠 Küsten in Gefahr'; }
|
||
else { state = 'bad'; txt = '🔴 Küsten überflutet'; }
|
||
sun.setAttribute('fill', temp > 3 ? '#e8833a' : '#f4c94e');
|
||
verdict.textContent = txt;
|
||
verdict.dataset.state = state;
|
||
}
|
||
rng.addEventListener('input', update);
|
||
update();
|
||
}
|
||
|
||
// =====================================================================
|
||
// Experiment: klimabilanz — Alltags-Entscheidungen → Jahres-CO₂
|
||
// =====================================================================
|
||
function klimabilanz(root) {
|
||
// Grundlast (Wohnen, Konsum, Öffentliches) fix
|
||
const BASE = 2.2;
|
||
const cats = [
|
||
{ key: 'food', q: '🍽️ Essen', opts: [
|
||
{ t: 'Viel Fleisch', v: 2.6 },
|
||
{ t: 'Gemischt', v: 1.7, sel: true },
|
||
{ t: 'Gemüse/vegetarisch', v: 1.0 } ] },
|
||
{ key: 'move', q: '🚗 Wege', opts: [
|
||
{ t: 'Meist Auto', v: 3.0 },
|
||
{ t: 'Gemischt', v: 1.5, sel: true },
|
||
{ t: 'Rad & Bus/Bahn', v: 0.4 } ] },
|
||
{ key: 'fly', q: '✈️ Flugreise', opts: [
|
||
{ t: 'Ein Fernflug', v: 2.0, sel: true },
|
||
{ t: 'Kein Flug', v: 0.0 } ] },
|
||
{ key: 'power', q: '💡 Strom', opts: [
|
||
{ t: 'Normalstrom', v: 1.2, sel: true },
|
||
{ t: 'Ökostrom', v: 0.2 } ] }
|
||
];
|
||
const chosen = {};
|
||
|
||
root.innerHTML = `
|
||
<div class="ge-wrap">
|
||
<div class="ge-head">
|
||
<h3>🌍 Deine Klimabilanz für ein Jahr</h3>
|
||
<p>Tippe an, wie du lebst. Der Balken zählt zusammen, wie viel CO₂ du in einem Jahr verursachst.</p>
|
||
</div>
|
||
<div class="ge-calc" id="kb-calc"></div>
|
||
<div class="ge-calc-result">
|
||
<div>Dein Jahres-Ausstoß:</div>
|
||
<strong class="ge-calc-total" id="kb-total">–</strong>
|
||
<div class="ge-calc-bar"><div class="ge-calc-fill" id="kb-bar" style="width:0%"></div></div>
|
||
<div class="ge-calc-scale"><span>0 t</span><span>Ziel 1 – 2 t</span><span>AT-Ø 8 t</span><span>12 t</span></div>
|
||
<div class="ge-calc-label" id="kb-verdict"></div>
|
||
</div>
|
||
<p class="ge-note">In Österreich verursacht jede Person rund 8 t CO₂ pro Jahr. Fürs Klima-Ziel wären es nur etwa 1 – 2 t. Quelle: Umweltbundesamt Österreich. Die Werte sind Richtgrößen, kein Messwert.</p>
|
||
</div>
|
||
`;
|
||
|
||
const box = root.querySelector('#kb-calc');
|
||
const totalOut = root.querySelector('#kb-total');
|
||
const barFill = root.querySelector('#kb-bar');
|
||
const verdict = root.querySelector('#kb-verdict');
|
||
if (!box) return;
|
||
|
||
cats.forEach(cat => {
|
||
const row = document.createElement('div');
|
||
row.className = 'ge-calc-row';
|
||
row.innerHTML = `<div class="ge-calc-q">${cat.q}</div><div class="ge-calc-opts" data-key="${cat.key}"></div>`;
|
||
const opts = row.querySelector('.ge-calc-opts');
|
||
cat.opts.forEach(o => {
|
||
const b = document.createElement('button');
|
||
b.className = 'ge-btn' + (o.sel ? ' ge-btn-primary' : '');
|
||
b.textContent = o.t;
|
||
b.dataset.val = o.v;
|
||
if (o.sel) chosen[cat.key] = o.v;
|
||
b.addEventListener('click', () => {
|
||
opts.querySelectorAll('.ge-btn').forEach(x => x.classList.remove('ge-btn-primary'));
|
||
b.classList.add('ge-btn-primary');
|
||
chosen[cat.key] = +b.dataset.val;
|
||
update();
|
||
});
|
||
opts.appendChild(b);
|
||
});
|
||
box.appendChild(row);
|
||
});
|
||
|
||
function update() {
|
||
const sum = BASE + Object.values(chosen).reduce((a, b) => a + b, 0);
|
||
totalOut.textContent = deNum(sum, 1) + ' t CO₂';
|
||
barFill.style.width = Math.min(100, (sum / 12) * 100) + '%';
|
||
let txt, col;
|
||
if (sum <= 2.5) { txt = '🟢 Super — nahe am Klima-Ziel!'; col = '#5a8a5e'; }
|
||
else if (sum <= 5) { txt = '🟡 Schon gut, geht noch weniger.'; col = '#4a7c8a'; }
|
||
else if (sum <= 8) { txt = '🟠 Etwa österreichischer Durchschnitt.'; col = '#e8833a'; }
|
||
else { txt = '🔴 Ziemlich viel — hier lässt sich sparen.'; col = '#c85c4a'; }
|
||
barFill.style.background = col;
|
||
verdict.textContent = txt;
|
||
}
|
||
update();
|
||
}
|
||
|
||
// =====================================================================
|
||
// Experiment: megawattstunde — wie lange reicht 1 MWh?
|
||
// =====================================================================
|
||
function megawattstunde(root) {
|
||
// 1 MWh = 1000 kWh
|
||
const items = [
|
||
{ key: 'led', label: '💡 LED-Lampe (10 W)', detail: (1000 / 0.010), unit: 'h', color: '#e8c547' },
|
||
{ key: 'kuehl',label: '🧊 Kühlschrank (150 kWh/Jahr)', detail: (1000 / 150) * 365, unit: 'd', color: '#4a7c8a' },
|
||
{ key: 'haus', label: '🏠 Haushalt (3.500 kWh/Jahr)', detail: (1000 / 3500) * 365, unit: 'd', color: '#5a8a5e' },
|
||
{ key: 'auto', label: '🚗 E-Auto (18 kWh/100 km)', detail: (1000 / 18) * 100, unit: 'km', color: '#c85c4a' }
|
||
];
|
||
|
||
root.innerHTML = `
|
||
<div class="ge-wrap">
|
||
<div class="ge-head">
|
||
<h3>⚡ Wie weit reicht 1 Megawattstunde?</h3>
|
||
<p>Eine Megawattstunde (1 MWh = 1.000 kWh) ist viel Energie. Tippe einen Verbraucher an und schau, wie lange oder wie weit sie reicht.</p>
|
||
</div>
|
||
<div class="ge-albedo-choice" id="mw-choice"></div>
|
||
<svg class="ge-gh-svg" viewBox="0 0 600 90" preserveAspectRatio="none" aria-hidden="true"></svg>
|
||
<div class="ge-gh-result">
|
||
<div class="ge-gh-pill">1 MWh reicht für: <strong id="mw-out">–</strong></div>
|
||
</div>
|
||
<p class="ge-note">Ein Durchschnittshaushalt in Österreich braucht rund 3.500 kWh Strom pro Jahr. Quelle: E-Control. Rechnung: 1.000 kWh : Verbrauch.</p>
|
||
</div>
|
||
`;
|
||
const choice = root.querySelector('#mw-choice');
|
||
const svg = root.querySelector('.ge-gh-svg');
|
||
const out = root.querySelector('#mw-out');
|
||
if (!choice || !svg) return;
|
||
|
||
const bar = svgEl('rect', { x: 0, y: 25, width: 0, height: 40, fill: '#4a7c8a', rx: 6 }, svg);
|
||
|
||
function fmtReach(it) {
|
||
if (it.unit === 'h') {
|
||
const years = it.detail / 24 / 365;
|
||
return deInt(it.detail) + ' Stunden Dauerlicht (≈ ' + deNum(years, 0) + ' Jahre)';
|
||
}
|
||
if (it.unit === 'd') {
|
||
const years = it.detail / 365;
|
||
if (years >= 1) return deNum(years, 1) + ' Jahre';
|
||
return deInt(it.detail) + ' Tage';
|
||
}
|
||
return deInt(it.detail) + ' km weit fahren';
|
||
}
|
||
|
||
function select(it) {
|
||
out.textContent = fmtReach(it);
|
||
// Balkenlänge auf logarithmischer Skala (Werte reichen von ~100 bis 100.000)
|
||
const logv = Math.log10(Math.max(10, it.detail));
|
||
const w = Math.min(1, (logv - 1) / 4) * 590 + 10;
|
||
bar.setAttribute('width', w);
|
||
bar.setAttribute('fill', it.color);
|
||
Array.from(choice.children).forEach(b => b.classList.toggle('ge-btn-primary', b.dataset.key === it.key));
|
||
}
|
||
|
||
items.forEach((it, i) => {
|
||
const b = document.createElement('button');
|
||
b.className = 'ge-btn' + (i === 0 ? ' ge-btn-primary' : '');
|
||
b.textContent = it.label;
|
||
b.dataset.key = it.key;
|
||
b.addEventListener('click', () => select(it));
|
||
choice.appendChild(b);
|
||
});
|
||
select(items[0]);
|
||
}
|
||
|
||
// =====================================================================
|
||
// Experiment: niederschlag — Regenmenge formt die Landschaft
|
||
// =====================================================================
|
||
function niederschlag(root) {
|
||
root.innerHTML = `
|
||
<div class="ge-wrap">
|
||
<div class="ge-head">
|
||
<h3>🌧️ Regen macht die Landschaft</h3>
|
||
<p>Schiebe den Regler von wenig zu viel Regen. Beobachte, wie aus trockener Steppe ein grüner Bergwald wird.</p>
|
||
</div>
|
||
<svg class="ge-track" viewBox="0 0 600 300" preserveAspectRatio="xMidYMid meet" aria-hidden="true"></svg>
|
||
<div class="ge-gh-slider">
|
||
<label for="ns-range">Regen pro Jahr: <strong id="ns-mm">300 mm</strong></label>
|
||
<input id="ns-range" type="range" min="300" max="3000" value="300" step="50">
|
||
<div class="ge-gh-markers"><span>300<br>Steppe</span><span>1.100<br>Wiese</span><span>3.000<br>Bergwald</span></div>
|
||
</div>
|
||
<div class="ge-gh-result">
|
||
<div class="ge-gh-pill" id="ns-verdict">–</div>
|
||
</div>
|
||
<p class="ge-note">In Österreich fallen im trockenen Osten (Seewinkel) unter 600 mm, im nassen Bregenzerwald über 2.000 mm Regen pro Jahr. Quelle: GeoSphere Austria.</p>
|
||
</div>
|
||
`;
|
||
const svg = root.querySelector('.ge-track');
|
||
const rng = root.querySelector('#ns-range');
|
||
const mmOut = root.querySelector('#ns-mm');
|
||
const verdict = root.querySelector('#ns-verdict');
|
||
if (!svg || !rng) return;
|
||
|
||
const sky = svgEl('rect', { x: 0, y: 0, width: 600, height: 200, fill: '#cfe3ea' }, svg);
|
||
const sun = svgEl('circle', { cx: 90, cy: 55, r: 28, fill: '#f4c94e' }, svg);
|
||
const cloud = svgEl('g', { opacity: '0' }, svg);
|
||
svgEl('ellipse', { cx: 300, cy: 45, rx: 70, ry: 26, fill: '#8fa6ad' }, cloud);
|
||
svgEl('ellipse', { cx: 360, cy: 55, rx: 55, ry: 22, fill: '#9fb4bb' }, cloud);
|
||
const rainG = svgEl('g', {}, svg);
|
||
// Hügel / Boden
|
||
const ground = svgEl('path', { d: 'M0,200 Q150,150 300,190 T600,180 L600,300 L0,300 Z', fill: '#c9b483' }, svg);
|
||
const vegG = svgEl('g', {}, svg);
|
||
|
||
function update() {
|
||
const mm = +rng.value;
|
||
mmOut.textContent = deInt(mm) + ' mm';
|
||
const frac = (mm - 300) / (3000 - 300); // 0..1
|
||
|
||
// Himmel wird grauer, Sonne blasser, Wolke + Regen erscheinen
|
||
sky.setAttribute('fill', frac < 0.5 ? '#cfe3ea' : '#b9ccd3');
|
||
sun.setAttribute('opacity', (1 - frac * 0.8).toFixed(2));
|
||
cloud.setAttribute('opacity', Math.min(1, frac * 1.4).toFixed(2));
|
||
|
||
// Boden wird grüner
|
||
const r = Math.round(201 - frac * 127);
|
||
const g = Math.round(180 + frac * 20);
|
||
const b = Math.round(131 - frac * 60);
|
||
ground.setAttribute('fill', `rgb(${r},${g},${b})`);
|
||
|
||
// Regentropfen
|
||
rainG.innerHTML = '';
|
||
const drops = Math.round(frac * 40);
|
||
for (let i = 0; i < drops; i++) {
|
||
const x = 250 + Math.random() * 160;
|
||
const y = 70 + Math.random() * 110;
|
||
svgEl('line', { x1: x, y1: y, x2: x - 4, y2: y + 12, stroke: '#4a7c8a', 'stroke-width': '2', 'stroke-linecap': 'round', opacity: '0.7' }, rainG);
|
||
}
|
||
|
||
// Vegetation: von einzelnen Grasbüscheln zu vielen Bäumen
|
||
vegG.innerHTML = '';
|
||
const plants = Math.round(4 + frac * 22);
|
||
for (let i = 0; i < plants; i++) {
|
||
const x = 20 + (i / plants) * 560 + (Math.sin(i * 3.1) * 12);
|
||
const baseY = 205 + (i % 3) * 22;
|
||
if (frac > 0.55 && i % 2 === 0) {
|
||
// Baum
|
||
const h = 26 + frac * 20;
|
||
svgEl('rect', { x: x - 2, y: baseY - h * 0.35, width: 4, height: h * 0.35, fill: '#6b4a2e' }, vegG);
|
||
svgEl('polygon', { points: `${x},${baseY - h} ${x - 12},${baseY - h * 0.35} ${x + 12},${baseY - h * 0.35}`, fill: '#3a6b3e' }, vegG);
|
||
} else {
|
||
// Grasbüschel — Farbe je nach Regen
|
||
const col = frac < 0.4 ? '#a89a5e' : '#5a8a5e';
|
||
svgEl('path', { d: `M${x},${baseY} l-3,-10 M${x},${baseY} l0,-13 M${x},${baseY} l3,-10`, stroke: col, 'stroke-width': '2', 'stroke-linecap': 'round', fill: 'none' }, vegG);
|
||
}
|
||
}
|
||
|
||
let state, txt;
|
||
if (mm < 600) { state = 'warn'; txt = '🏜️ Trockene Steppe'; }
|
||
else if (mm < 1500) { state = 'now'; txt = '🌱 Grüne Wiesen & Felder'; }
|
||
else { state = 'good'; txt = '🌲 Dichter Bergwald'; }
|
||
verdict.textContent = txt;
|
||
verdict.dataset.state = state;
|
||
}
|
||
rng.addEventListener('input', update);
|
||
update();
|
||
}
|
||
|
||
// =====================================================================
|
||
// Experiment: fruchtfolge — 3 Jahre Feld planen, Bodengesundheit
|
||
// =====================================================================
|
||
function fruchtfolge(root) {
|
||
// effect = Wirkung auf Boden; legume = Stickstoff-Sammler
|
||
const plants = [
|
||
{ key: 'weizen', label: '🌾 Weizen', effect: -6, legume: false },
|
||
{ key: 'mais', label: '🌽 Mais', effect: -12, legume: false },
|
||
{ key: 'kartoffel', label: '🥔 Kartoffel', effect: -12, legume: false },
|
||
{ key: 'erbsen', label: '🫛 Erbsen', effect: 15, legume: true },
|
||
{ key: 'klee', label: '☘️ Klee', effect: 15, legume: true }
|
||
];
|
||
const years = [null, null, null];
|
||
|
||
root.innerHTML = `
|
||
<div class="ge-wrap">
|
||
<div class="ge-head">
|
||
<h3>🚜 Plane dein Feld für 3 Jahre</h3>
|
||
<p>Wähle für jedes Jahr eine Pflanze. Baust du immer dasselbe an (Monokultur), wird der Boden müde. Ein Wechsel — vor allem mit Erbsen oder Klee — hält ihn gesund.</p>
|
||
</div>
|
||
<div class="ge-calc" id="ff-years"></div>
|
||
<div class="ge-calc-result">
|
||
<div>Bodengesundheit nach 3 Jahren:</div>
|
||
<strong class="ge-calc-total" id="ff-total">60 %</strong>
|
||
<div class="ge-calc-bar"><div class="ge-calc-fill" id="ff-bar" style="width:60%"></div></div>
|
||
<div class="ge-calc-scale"><span>ausgelaugt</span><span></span><span>gesund</span></div>
|
||
<div class="ge-calc-label" id="ff-verdict"></div>
|
||
</div>
|
||
<p class="ge-note">Erbsen und Klee sind Hülsenfrüchte: Sie sammeln mit Knöllchenbakterien Stickstoff aus der Luft und düngen so den Boden. Deshalb wechseln Bäuerinnen und Bauern die Feldfrüchte planmäßig ab (Fruchtfolge). Quelle: AGES / Landwirtschaftskammer.</p>
|
||
</div>
|
||
`;
|
||
const box = root.querySelector('#ff-years');
|
||
const totalOut = root.querySelector('#ff-total');
|
||
const barFill = root.querySelector('#ff-bar');
|
||
const verdict = root.querySelector('#ff-verdict');
|
||
if (!box) return;
|
||
|
||
for (let y = 0; y < 3; y++) {
|
||
const row = document.createElement('div');
|
||
row.className = 'ge-calc-row';
|
||
row.innerHTML = `<div class="ge-calc-q">Jahr ${y + 1}</div><div class="ge-calc-opts" data-year="${y}"></div>`;
|
||
const opts = row.querySelector('.ge-calc-opts');
|
||
plants.forEach(p => {
|
||
const b = document.createElement('button');
|
||
b.className = 'ge-btn';
|
||
b.textContent = p.label;
|
||
b.dataset.key = p.key;
|
||
b.addEventListener('click', () => {
|
||
opts.querySelectorAll('.ge-btn').forEach(x => x.classList.remove('ge-btn-primary'));
|
||
b.classList.add('ge-btn-primary');
|
||
years[y] = p.key;
|
||
update();
|
||
});
|
||
opts.appendChild(b);
|
||
});
|
||
box.appendChild(row);
|
||
}
|
||
|
||
function update() {
|
||
let health = 60; // Startwert
|
||
let mono = 0;
|
||
for (let y = 0; y < 3; y++) {
|
||
const key = years[y];
|
||
if (!key) continue;
|
||
const p = plants.find(x => x.key === key);
|
||
health += p.effect;
|
||
// Monokultur-Strafe: gleiche Pflanze wie im Vorjahr
|
||
if (y > 0 && years[y - 1] === key) { health -= 10; mono++; }
|
||
}
|
||
health = Math.max(0, Math.min(100, health));
|
||
totalOut.textContent = Math.round(health) + ' %';
|
||
barFill.style.width = health + '%';
|
||
|
||
let txt, col;
|
||
if (health >= 75) { txt = '🟢 Toll — der Boden ist gesund und fruchtbar.'; col = '#5a8a5e'; }
|
||
else if (health >= 50) { txt = '🟡 Ok — mit mehr Wechsel geht es besser.'; col = '#4a7c8a'; }
|
||
else if (health >= 30) { txt = '🟠 Der Boden wird müde.'; col = '#e8833a'; }
|
||
else { txt = '🔴 Ausgelaugt — der Boden braucht eine Pause.'; col = '#c85c4a'; }
|
||
if (mono >= 2) txt = '🔴 Monokultur! Immer dasselbe laugt den Boden aus.';
|
||
barFill.style.background = col;
|
||
verdict.textContent = txt;
|
||
}
|
||
update();
|
||
}
|
||
|
||
// Registry — Keys = key_slug aus DB.
|
||
window.GlossarExperiments = Object.assign(window.GlossarExperiments || {}, {
|
||
'strommix': strommix,
|
||
'eisschild': eisschild,
|
||
'klimabilanz': klimabilanz,
|
||
'megawattstunde': megawattstunde,
|
||
'niederschlag': niederschlag,
|
||
'fruchtfolge': fruchtfolge
|
||
});
|
||
})();
|