fecd8bb9c9
562 Ersetzungen in 50 Dateien: Halbgeviertstrich zwischen zwei Ziffern (= "bis"-Bereich) bekommt Leerzeichen davor/danach (3–4 -> 3 – 4). Regex /([0-9])\s*–\s*(?=[0-9])/ auf Rohtext (format-erhaltend, CRLF/Einrueckung unveraendert), Bindestriche in Woertern und Minuszeichen unangetastet, alle JSON weiter gueltig. Energiemanager-Zeitbloecke sind Display-Labels (kein Logik-Key) -> safe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1537 lines
63 KiB
HTML
1537 lines
63 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8"/>
|
||
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
|
||
<title>GeoGraSim — Lernen durch Simulation · Präsentation</title>
|
||
<link rel="icon" type="image/png" href="../../favicon-96x96.png" sizes="96x96"/>
|
||
<link rel="icon" type="image/svg+xml" href="../../favicon.svg"/>
|
||
<script src="../API Key.js"></script>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reset.css"/>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.css"/>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.css"/>
|
||
<link rel="stylesheet" href="fonts/fonts.css"/>
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/katex.min.js"></script>
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.10/dist/contrib/auto-render.min.js"></script>
|
||
<style>
|
||
:root {
|
||
--brand: #163374;
|
||
--bar-h: 52px;
|
||
}
|
||
|
||
/* ── Base ── */
|
||
.reveal {
|
||
font-family: system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
|
||
font-size: 32px;
|
||
color: #111;
|
||
background: #fff;
|
||
}
|
||
.reveal h1 { font-size: 1.8em; font-weight: 700; line-height: 1.1; margin-bottom: 0.35em; }
|
||
.reveal h2 { font-size: 1.15em; font-weight: 700; line-height: 1.2; margin-bottom: 0.35em; }
|
||
.reveal h3 { font-size: 0.68em; font-weight: 600; text-transform: uppercase; letter-spacing: 0.12em; color: #888; margin: 0.8em 0 0.3em; }
|
||
.reveal p, .reveal li { font-size: 0.78em; line-height: 1.75; color: #333; }
|
||
.reveal p { margin-bottom: 0.35em; }
|
||
.reveal strong { font-weight: 700; color: #111; }
|
||
.reveal em { font-style: italic; }
|
||
.reveal a { color: var(--brand); }
|
||
.reveal ul { list-style: none; padding: 0; margin: 0; }
|
||
.reveal ul li { padding-left: 1.1em; position: relative; margin-bottom: 0.3em; }
|
||
.reveal ul li::before { content: '–'; position: absolute; left: 0; color: #aaa; }
|
||
.reveal ol li { margin-bottom: 0.3em; }
|
||
.reveal .slides section { padding-bottom: calc(var(--bar-h) + 16px) !important; box-sizing: border-box; text-align: left; }
|
||
.reveal .progress span { background: var(--brand); }
|
||
.reveal .controls { color: var(--brand); bottom: calc(var(--bar-h) + 10px) !important; }
|
||
|
||
/* ── Footer bar ── */
|
||
#slide-footer-bar {
|
||
position: fixed; bottom: 0; left: 0; right: 0;
|
||
height: var(--bar-h); background: var(--brand);
|
||
display: flex; align-items: center; padding: 0 2em;
|
||
z-index: 200;
|
||
}
|
||
#footer-logo { height: 26px; width: 26px; opacity: 0.85; color: rgba(255,255,255,.9); flex-shrink: 0; }
|
||
#footer-num { position: absolute; left: 50%; transform: translateX(-50%); font-size: 11px; color: rgba(255,255,255,.45); letter-spacing: .1em; font-family: system-ui; }
|
||
#footer-clock { margin-left: auto; font-size: 12px; color: rgba(255,255,255,.45); font-family: system-ui; font-variant-numeric: tabular-nums; }
|
||
#slide-footer-bar.bar-light { background: #fff; box-shadow: 0 -1px 0 rgba(0,0,0,.1); }
|
||
#slide-footer-bar.bar-light #footer-num,
|
||
#slide-footer-bar.bar-light #footer-clock { color: rgba(22,51,116,.4); }
|
||
#slide-footer-bar.bar-light #footer-logo { color: var(--brand); }
|
||
|
||
/* ── UI buttons ── */
|
||
.home-btn {
|
||
position: fixed; top: 1em; right: 1em; width: 1.9em; height: 1.9em;
|
||
border-radius: 50%; border: 1px solid rgba(0,0,0,.15); background: rgba(255,255,255,.9);
|
||
color: #555; font-size: 1em; display: flex; align-items: center; justify-content: center;
|
||
text-decoration: none; z-index: 300; box-shadow: 0 1px 4px rgba(0,0,0,.1);
|
||
}
|
||
.home-btn.light { color: var(--brand); }
|
||
.fab {
|
||
width: 1.9em; height: 1.9em; border-radius: 50%; border: 1px solid rgba(0,0,0,.15);
|
||
background: rgba(255,255,255,.9); color: #555; font-size: 1em; cursor: pointer;
|
||
display: flex; align-items: center; justify-content: center; text-decoration: none;
|
||
box-shadow: 0 1px 4px rgba(0,0,0,.1);
|
||
}
|
||
.fab.light { color: var(--brand); }
|
||
/* ── Collapsible FAB cluster ── */
|
||
#fab-cluster {
|
||
position: fixed; top: 1em; right: 3.5em;
|
||
display: flex; align-items: center; gap: .4em;
|
||
z-index: 300;
|
||
}
|
||
#fab-tools {
|
||
display: flex; gap: .4em; align-items: center;
|
||
max-width: 0; overflow: hidden; opacity: 0;
|
||
transition: max-width .28s ease, opacity .2s ease;
|
||
}
|
||
#fab-cluster.open #fab-tools { max-width: 22em; opacity: 1; }
|
||
#img-btn.generating { animation: spin 1.2s linear infinite; cursor: default; }
|
||
@keyframes spin { to { transform: rotate(360deg); } }
|
||
|
||
/* ── Toast ── */
|
||
#img-toast {
|
||
position: fixed; bottom: calc(var(--bar-h) + 12px); left: 50%; transform: translateX(-50%);
|
||
background: rgba(22,51,116,.92); color: #fff; font-size: .7rem; padding: .38rem 1.1rem;
|
||
border-radius: 20px; pointer-events: none; opacity: 0; transition: opacity .4s;
|
||
z-index: 400; white-space: nowrap; font-family: system-ui;
|
||
}
|
||
|
||
@media print { #slide-footer-bar, #img-toast { display: none; } .reveal section { page-break-after: always; } }
|
||
|
||
/* ══ LAYOUT-VARIANTEN ══
|
||
Gradient-Modus: Der Verlauf ist direkt in das KI-generierte Bild eingebacken —
|
||
linke Seite weiß (Textbereich lesbar), rechte Seite volles Motiv.
|
||
Kein CSS-Overlay nötig, Opacity 1. */
|
||
|
||
/* ══ UI PANELS ══ */
|
||
.ui-panel {
|
||
display: none;
|
||
position: fixed;
|
||
bottom: calc(var(--bar-h) + 14px);
|
||
right: 1em;
|
||
background: #fff;
|
||
border: 1px solid #e0e0e0;
|
||
border-radius: 10px;
|
||
padding: 1.1em 1.2em;
|
||
z-index: 350;
|
||
box-shadow: 0 6px 28px rgba(0,0,0,.16);
|
||
min-width: 280px;
|
||
max-width: 340px;
|
||
}
|
||
.ui-panel.open { display: block; }
|
||
.panel-title {
|
||
font-size: .65rem; font-weight: 700; text-transform: uppercase;
|
||
letter-spacing: .12em; color: #999; margin-bottom: .85em;
|
||
font-family: system-ui;
|
||
}
|
||
|
||
/* Layout panel */
|
||
.layout-opts { display: flex; gap: .6em; }
|
||
.layout-opt {
|
||
flex: 1; border: 2px solid #e0e0e0; border-radius: 8px;
|
||
padding: .6em .4em; cursor: pointer; background: #fafafa;
|
||
transition: border-color .15s, background .15s; text-align: center;
|
||
}
|
||
.layout-opt:hover { border-color: var(--brand); background: #f0f4fd; }
|
||
.layout-opt.active { border-color: var(--brand); background: #eef2fc; }
|
||
.lo-icon { font-size: 1.4em; margin-bottom: .25em; color: #444; }
|
||
.lo-name { font-size: .62rem; font-weight: 700; color: #222; font-family: system-ui; }
|
||
.lo-desc { font-size: .55rem; color: #888; margin-top: .15em; font-family: system-ui; line-height: 1.4; }
|
||
|
||
/* Font panel */
|
||
.font-opts { display: flex; flex-direction: column; gap: .5em; }
|
||
.font-opt {
|
||
border: 2px solid #e8e8e8; border-radius: 7px; padding: .55em .9em;
|
||
cursor: pointer; background: #fafafa; transition: border-color .15s;
|
||
display: flex; align-items: center; gap: .8em;
|
||
}
|
||
.font-opt:hover { border-color: var(--brand); }
|
||
.font-opt.active { border-color: var(--brand); background: #eef2fc; }
|
||
.fo-sample { font-size: 1.15em; font-weight: 700; color: #111; flex-shrink: 0; width: 2.8em; }
|
||
.fo-info { flex: 1; }
|
||
.fo-name { font-size: .66rem; font-weight: 700; color: #222; font-family: system-ui; }
|
||
.fo-pair { font-size: .58rem; color: #888; font-family: system-ui; }
|
||
|
||
/* Color panel */
|
||
.color-swatches { display: flex; flex-wrap: wrap; gap: .4em; margin-bottom: .75em; }
|
||
.color-swatch {
|
||
width: 2em; height: 2em; border-radius: 50%; cursor: pointer;
|
||
border: 2px solid transparent; transition: transform .12s, border-color .12s;
|
||
box-shadow: 0 1px 4px rgba(0,0,0,.12);
|
||
}
|
||
.color-swatch:hover { transform: scale(1.15); border-color: #555; }
|
||
.color-row { display: flex; align-items: center; gap: .6em; margin-top: .4em; }
|
||
.color-row input[type=color] {
|
||
width: 2.2em; height: 2.2em; border: none; border-radius: 4px;
|
||
cursor: pointer; padding: 0; background: none;
|
||
}
|
||
.color-row label { font-size: .62rem; color: #666; font-family: system-ui; }
|
||
.panel-btn {
|
||
width: 100%; padding: .45em; font-size: .65rem; border-radius: 6px;
|
||
border: 1px solid #ddd; background: #f5f5f5; cursor: pointer;
|
||
font-family: system-ui; margin-top: .5em; color: #444;
|
||
transition: background .15s;
|
||
}
|
||
.panel-btn:hover { background: #eee; }
|
||
.panel-btn.danger { border-color: #f5a0a0; color: #b71c1c; background: #fff5f5; }
|
||
.panel-btn.danger:hover { background: #fde8e8; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="reveal">
|
||
<div class="slides">
|
||
|
||
<!-- 01 TITEL -->
|
||
<section>
|
||
<h1>Lernen durch<br>Simulation</h1>
|
||
<p>Wie interaktive Simulationen im Geografieunterricht wirken —<br>Forschung, Mechanismen, Gestaltung</p>
|
||
<p>Thomas Schroffenegger<br>
|
||
GeoGraSim — Plattform für Geografie-Simulationen<br>
|
||
Sekundarstufe I · 2026</p>
|
||
</section>
|
||
|
||
<!-- 02 ZÄSUR -->
|
||
<section>
|
||
<h3>Befund aus 30 Jahren Forschung</h3>
|
||
<h1>Simulationen wirken — wenn sie gut gemacht sind</h1>
|
||
<p>Meta-Analysen über Hunderte Studien zeigen ein klares Bild</p>
|
||
<ul>
|
||
<li>Mittlere Effektstärke <strong>d ≈ 0,40</strong> für Lernergebnisse — gegenüber traditionellem Unterricht</li>
|
||
<li>In den Naturwissenschaften deutlich über <strong>d > 0,50</strong></li>
|
||
<li>Stärkster Effekt: Verständnis von <strong>komplexen, dynamischen Systemen</strong></li>
|
||
</ul>
|
||
<p>D'Angelo et al., 2014 · Vlachopoulos & Makri, 2017 · Smetana & Bell, 2012</p>
|
||
</section>
|
||
|
||
<!-- 03 DIE FRAGE -->
|
||
<section>
|
||
<h2>Warum Simulationen im Geografieunterricht?</h2>
|
||
<p>Klimasysteme, Wirtschaftskreisläufe, Naturgefahren, Flussdynamik — viele Kerninhalte sind <strong>räumlich verteilt, zeitlich gestreckt, multikausal</strong>. Direkter Anschauung kaum zugänglich.</p>
|
||
<p>Simulationen machen genau das sichtbar und manipulierbar: Was-wäre-wenn als didaktisches Werkzeug.</p>
|
||
<ul>
|
||
<li>Statt Lesen über Klima → Klima <strong>einstellen</strong> und Folgen sehen</li>
|
||
<li>Statt Lehrtexte zur Stadt → Stadt <strong>planen</strong> und Konflikte erleben</li>
|
||
<li>Statt Erklärung des Schwemmlands → Fluss <strong>verlegen</strong> und Auswirkungen messen</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 04 ÜBERBLICK -->
|
||
<section>
|
||
<h2>Überblick</h2>
|
||
<h3>Theoretischer Teil</h3>
|
||
<ol>
|
||
<li>Grundlagen — Was ist eine Simulation?</li>
|
||
<li>Typen — vom Mikroweltchen bis VR</li>
|
||
<li>Empirische Wirksamkeit</li>
|
||
<li>Gestaltungsprinzipien</li>
|
||
</ol>
|
||
<h3>Praxis-Teil</h3>
|
||
<ol start="5">
|
||
<li>Rolle der Lehrperson</li>
|
||
<li>Anwendung im Geografieunterricht</li>
|
||
<li>Qualitätskriterien</li>
|
||
<li>Herausforderungen & Ausblick</li>
|
||
</ol>
|
||
<p>Basis: 195 peer-reviewed Quellen · Stand April 2026 · GeoGraSim-Praxisrahmen</p>
|
||
</section>
|
||
|
||
<!-- KAPITEL 1 -->
|
||
<section>
|
||
<h3>Kapitel 1 — Grundlagen</h3>
|
||
<h1>Was ist eine<br>Simulation?</h1>
|
||
</section>
|
||
|
||
<!-- 06 DEFINITION -->
|
||
<section>
|
||
<h2>Simulation — eine Arbeitsdefinition</h2>
|
||
<p>Eine <strong>Simulation</strong> ist die regelhafte Nachbildung eines realen oder gedachten Systems mit dem Zweck, sein Verhalten unter veränderten Bedingungen sichtbar zu machen.</p>
|
||
<h3>Drei Bestandteile</h3>
|
||
<ul>
|
||
<li><strong>Modell:</strong> Reduktion des Systems auf wesentliche Variablen</li>
|
||
<li><strong>Regelwerk:</strong> Wie reagieren die Variablen aufeinander?</li>
|
||
<li><strong>Interaktion:</strong> Lernende greifen ein, beobachten Folgen</li>
|
||
</ul>
|
||
<p><em>Lerntheoretisch verwurzelt im Konstruktivismus, in der Cognitive Load Theory und in der Multimedia Learning Theory (Mayer).</em></p>
|
||
</section>
|
||
|
||
<!-- 07 LERNTHEORIE -->
|
||
<section>
|
||
<h2>Drei Theorien — ein roter Faden</h2>
|
||
<h3>Konstruktivismus (Piaget, Wygotski)</h3>
|
||
<p>Wissen entsteht aktiv. Lernende konstruieren Bedeutung im Tun, nicht im Empfangen.</p>
|
||
<h3>Cognitive Load Theory (Sweller)</h3>
|
||
<p>Das Arbeitsgedächtnis ist eng. Gute Simulationen reduzieren <em>extraneous</em> Last und fördern <em>germane</em> Last (Schemabildung).</p>
|
||
<h3>Multimedia Learning Theory (Mayer)</h3>
|
||
<p>Bild + Sprache zusammen wirken stärker als beides isoliert — wenn räumliche und zeitliche Nähe stimmen.</p>
|
||
</section>
|
||
|
||
<!-- 08 FORSCHUNGSSTAND -->
|
||
<section>
|
||
<h2>Stand der Forschung</h2>
|
||
<ul>
|
||
<li><strong>1.871</strong> Publikationen zu Simulationen im Unterricht in den letzten 15 Jahren</li>
|
||
<li>Über <strong>50</strong> Meta-Analysen seit 2010</li>
|
||
<li>Befund: <strong>moderate bis starke Effekte</strong> auf Wissen, Verstehen, Motivation</li>
|
||
</ul>
|
||
<p>Stärkste Wirkung dort, wo direkte Anschauung schwer ist: Astronomie, Klima, Genetik, Mikrobiologie — und Geografie.</p>
|
||
<p>Smetana & Bell 2012 · D'Angelo et al. 2014 · Lamb et al. 2018</p>
|
||
</section>
|
||
|
||
<!-- KAPITEL 2 -->
|
||
<section>
|
||
<h3>Kapitel 2 — Typen</h3>
|
||
<h1>Welche Arten von<br>Simulationen?</h1>
|
||
</section>
|
||
|
||
<!-- 10 KLASSIFIKATION -->
|
||
<section>
|
||
<h2>Klassifikation nach Interaktionsgrad</h2>
|
||
<h3>Beobachtende Simulation</h3>
|
||
<p>Lernende sehen einem Modell zu, ändern Parameter selten — z. B. Animation des Wasserkreislaufs.</p>
|
||
<h3>Manipulative Simulation</h3>
|
||
<p>Lernende ändern aktiv Variablen, beobachten Folgen — Kernform für entdeckendes Lernen.</p>
|
||
<h3>Modellbildende Simulation</h3>
|
||
<p>Lernende konstruieren das Modell selbst — höchste Anforderung, größtes Lernpotenzial.</p>
|
||
</section>
|
||
|
||
<!-- 11 BEISPIELE -->
|
||
<section>
|
||
<h2>Vier prägende Familien</h2>
|
||
<h3>PhET (Univ. Colorado)</h3>
|
||
<p>180+ frei zugängliche Simulationen, 200 Mio. Aufrufe — Goldstandard für offene Exploration.</p>
|
||
<h3>Serious Games & Lernspiele</h3>
|
||
<p>Narrativ + Simulation — z. B. <em>Climate Quest</em>, <em>EcoMUVE</em>. Motivation hoch, Transfer fragil.</p>
|
||
<h3>Virtuelle Labore</h3>
|
||
<p>Experimente sicher, beliebig wiederholbar — sehr gefragt seit der Pandemie.</p>
|
||
<h3>VR / AR & agentenbasierte Modelle</h3>
|
||
<p>Räumliche Immersion bzw. emergentes Systemverhalten — Forschungsfront, didaktisch noch jung.</p>
|
||
</section>
|
||
|
||
<!-- KAPITEL 3 -->
|
||
<section>
|
||
<h3>Kapitel 3 — Wirksamkeit</h3>
|
||
<h1>Was Studien<br>tatsächlich zeigen</h1>
|
||
</section>
|
||
|
||
<!-- 13 META-ANALYSEN -->
|
||
<section>
|
||
<h2>Meta-analytische Befunde</h2>
|
||
<ul>
|
||
<li><strong>D'Angelo et al. 2014</strong> — 59 Studien · g = 0,42 für Wissenserwerb</li>
|
||
<li><strong>Vlachopoulos & Makri 2017</strong> — Spiele/Simulationen · positiver Effekt auf alle Lerndomänen</li>
|
||
<li><strong>Smetana & Bell 2012</strong> — Computersimulationen ≥ konventioneller Unterricht in 28 von 38 Studien</li>
|
||
<li><strong>Merchant et al. 2014</strong> — VR-Lernumgebungen · d = 0,41</li>
|
||
</ul>
|
||
<p>Wirkung steigt mit guter Einbettung, Scaffolding und kompetenter Lehrperson — sie sinkt bei reinem „Selbsterkundigen ohne Anleitung".</p>
|
||
</section>
|
||
|
||
<!-- 14 OUTCOMES -->
|
||
<section>
|
||
<h2>Was Simulationen besonders gut können</h2>
|
||
<h3>Kognitive Outcomes</h3>
|
||
<ul>
|
||
<li>Verständnis dynamischer, vernetzter Systeme</li>
|
||
<li>Begriffsbildung bei abstrakten Konzepten</li>
|
||
<li>Multiple Repräsentationen — Karte, Diagramm, Animation parallel</li>
|
||
</ul>
|
||
<h3>Affektive & motivationale Outcomes</h3>
|
||
<ul>
|
||
<li>Höheres Selbstwirksamkeitserleben</li>
|
||
<li>Stärkeres Fachinteresse, längerfristiger Beschäftigungswille</li>
|
||
<li>Senkung der Eintrittsschwelle bei vermeintlich „schweren" Themen</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 15 TRANSFER -->
|
||
<section>
|
||
<h2>Virtuell vs. real — und der Transfer</h2>
|
||
<p>Virtuelle Experimente schlagen reale nicht — sie ergänzen sie. Beste Ergebnisse zeigen <em>Hybride</em>: erst Simulation, dann reale Beobachtung — oder umgekehrt.</p>
|
||
<ul>
|
||
<li><strong>Naher Transfer</strong> (gleiche Aufgabenklasse) gelingt zuverlässig</li>
|
||
<li><strong>Ferner Transfer</strong> (Übertragung in neuen Kontext) braucht explizite Reflexion</li>
|
||
<li><strong>Schlüsselbedingung:</strong> Verbindung zwischen Modell und realer Welt muss explizit gemacht werden</li>
|
||
</ul>
|
||
<p>de Jong et al. 2013 · Olympiou & Zacharia 2012</p>
|
||
</section>
|
||
|
||
<!-- KAPITEL 4 -->
|
||
<section>
|
||
<h3>Kapitel 4 — Gestaltung</h3>
|
||
<h1>Was eine gute<br>Simulation ausmacht</h1>
|
||
</section>
|
||
|
||
<!-- 17 PRINZIPIEN -->
|
||
<section>
|
||
<h2>Sechs Gestaltungsprinzipien</h2>
|
||
<h3>01 — Klare visuelle Sprache</h3>
|
||
<p>Reduktion auf Wesentliches, konsistente Farbcodes, lesbare Typografie.</p>
|
||
<h3>02 — Intuitive Bedienbarkeit</h3>
|
||
<p>Erste Interaktion in unter einer Minute möglich — sonst geht der Lerneffekt verloren.</p>
|
||
<h3>03 — Echte Interaktivität</h3>
|
||
<p>Parameter veränderbar, Ergebnis sofort sichtbar, Fehlversuche kostenfrei.</p>
|
||
<h3>04 — Eingebautes Scaffolding</h3>
|
||
<p>Hinweise, gestufte Aufgaben, Reflexionsimpulse — nicht versteckt, sondern führbar.</p>
|
||
<h3>05 — Multiple Repräsentationen</h3>
|
||
<p>Karte + Graph + Tabelle + Text — verknüpft, nicht isoliert.</p>
|
||
<h3>06 — Lebensweltbezug</h3>
|
||
<p>Daten und Szenarien, die für Schüler*innen erkennbar relevant sind.</p>
|
||
</section>
|
||
|
||
<!-- 18 COGNITIVE LOAD -->
|
||
<section>
|
||
<h2>Cognitive Load — die unsichtbare Hürde</h2>
|
||
<p>Schüler*innen scheitern selten am Inhalt. Sie scheitern oft an Oberflächenfunktionen, die Aufmerksamkeit binden.</p>
|
||
<h3>Was extraneous Load erzeugt</h3>
|
||
<ul>
|
||
<li>Funktionsbuttons, deren Bedeutung erst gelernt werden muss</li>
|
||
<li>Animationen ohne Lernfunktion</li>
|
||
<li>Räumlich getrennte Information (Text rechts, Bild links)</li>
|
||
</ul>
|
||
<h3>Was germane Load fördert</h3>
|
||
<ul>
|
||
<li>Reflexionsfragen direkt im Werkzeug</li>
|
||
<li>Kontrastbeispiele — „was wäre, wenn …"</li>
|
||
<li>Zwischenschritte sichtbar machen statt nur Endergebnisse</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- KAPITEL 5 -->
|
||
<section>
|
||
<h3>Kapitel 5 — Lehrperson</h3>
|
||
<h1>Die Rolle der<br>Lehrperson</h1>
|
||
</section>
|
||
|
||
<!-- 20 LERNBEGLEITUNG -->
|
||
<section>
|
||
<h2>Vom Wissensvermittler zur Lernbegleiterin</h2>
|
||
<p>Mit der Simulation ändert sich der Beruf nicht — aber das Tagesgeschäft schon.</p>
|
||
<h3>Vorher</h3>
|
||
<ul>
|
||
<li>Erklärt das System</li>
|
||
<li>Stellt Aufgaben mit klarer Lösung</li>
|
||
<li>Korrigiert Ergebnisse</li>
|
||
</ul>
|
||
<h3>Mit Simulation</h3>
|
||
<ul>
|
||
<li>Stellt produktive Fragen, lässt das System für sich sprechen</li>
|
||
<li>Beobachtet, wo Lernende hängen bleiben — und greift gezielt ein</li>
|
||
<li>Moderiert das Gespräch über Modell vs. Wirklichkeit</li>
|
||
</ul>
|
||
<p><em>On-the-Fly Scaffolding</em> — situative Hilfe statt Vorab-Erklärung — wird zur Kernkompetenz.</p>
|
||
</section>
|
||
|
||
<!-- 21 DREIECK -->
|
||
<section>
|
||
<h2>Das Dreieck: Lernende — Simulation — Lehrperson</h2>
|
||
<p>Keine der drei Ecken funktioniert alleine. Die Simulation ist Werkzeug, nicht Ersatz.</p>
|
||
<ul>
|
||
<li><strong>Simulation ↔ Lernende:</strong> direkte Manipulation, sofortiges Feedback</li>
|
||
<li><strong>Lernende ↔ Lehrperson:</strong> Reflexion, Bedeutungsaushandlung, soziales Lernen</li>
|
||
<li><strong>Lehrperson ↔ Simulation:</strong> Auswahl, Vorbereitung, Didaktisierung — Inszenierung des Lernanlasses</li>
|
||
</ul>
|
||
<p>Studienbefund: Bei kompetenter Begleitung steigt die Effektstärke um den Faktor 1,5 – 2.</p>
|
||
</section>
|
||
|
||
<!-- KAPITEL 6 -->
|
||
<section>
|
||
<h3>Kapitel 6 — Geografie</h3>
|
||
<h1>Anwendung im<br>GW-Unterricht</h1>
|
||
</section>
|
||
|
||
<!-- 23 EIGNUNG -->
|
||
<section>
|
||
<h2>Warum Geografie besonders profitiert</h2>
|
||
<p>Kein anderes Schulfach arbeitet mit so vielen Maßstabsebenen, langen Zeithorizonten und vernetzten Systemen — und steht so oft vor dem Problem, das eigentlich Spannende nicht direkt zeigen zu können.</p>
|
||
<ul>
|
||
<li><strong>Räumliches Denken</strong> — Karten, Profile, 3D-Ansichten ineinander überführen</li>
|
||
<li><strong>Maßstabswechsel</strong> — vom Hangrutsch bis zur globalen Erwärmung</li>
|
||
<li><strong>Zeitliche Streckung</strong> — Klimawandel, Urbanisierung, Migration in beschleunigter Form</li>
|
||
<li><strong>Multikausalität</strong> — viele Variablen wirken gleichzeitig — sichtbar machen</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- 24 ANWENDUNGSFELDER -->
|
||
<section>
|
||
<h2>Drei starke Anwendungsfelder</h2>
|
||
<h3>Klimawandel & Nachhaltigkeit</h3>
|
||
<p>Treibhauseffekt, Energiemix, regionale Klimafolgen — manipulierbar statt erzählt.</p>
|
||
<h3>Naturgefahren</h3>
|
||
<p>Hochwasser, Erdbeben, Hangrutsch — ohne reale Gefahr durchspielen, Risiken einordnen.</p>
|
||
<h3>Stadtentwicklung & Raumplanung</h3>
|
||
<p>Verkehr, Wohnraum, Grünflächen, Migration — Zielkonflikte als Lernanlass.</p>
|
||
<p><em>Plus:</em> Logistik, Landwirtschaft, Energiesysteme, Geomedien/GIS.</p>
|
||
</section>
|
||
|
||
<!-- 25 LEHRPLAN -->
|
||
<section>
|
||
<h2>Bezug zum österreichischen Lehrplan</h2>
|
||
<p>Der GW-Lehrplan 2023 für die Sekundarstufe I verlangt explizit den Einsatz <strong>digitaler Werkzeuge</strong>, <strong>Modellbildung</strong> und <strong>Systemverständnis</strong> — Simulationen sind dafür der natürliche Träger.</p>
|
||
<ul>
|
||
<li><strong>1. Klasse</strong> — Leben und Wirtschaften → Klima, Wetter, Naturraum</li>
|
||
<li><strong>2. Klasse</strong> — Nachhaltigkeit → Energie, Ressourcen, Kreisläufe</li>
|
||
<li><strong>3. Klasse</strong> — Österreich → Verkehr, Logistik, Wirtschaft</li>
|
||
<li><strong>4. Klasse</strong> — Globalisierte Welt → Klimawandel, Migration, Welthandel</li>
|
||
</ul>
|
||
<p>Alle vier Klassenstufen verlangen <em>Anwendungs- und Methodenkompetenz</em> — direkt simulationsnah.</p>
|
||
</section>
|
||
|
||
<!-- KAPITEL 7 -->
|
||
<section>
|
||
<h3>Kapitel 7 — Qualität</h3>
|
||
<h1>Wie unterscheidet man<br>gute Simulationen?</h1>
|
||
</section>
|
||
|
||
<!-- 27 SECHS DIMENSIONEN -->
|
||
<section>
|
||
<h2>Sechs Dimensionen der Qualität</h2>
|
||
<ol>
|
||
<li><strong>Fachliche Korrektheit</strong> — das Modell entspricht dem aktuellen wissenschaftlichen Stand</li>
|
||
<li><strong>Interaktivität & Explorationstiefe</strong> — genug Variabeln, sinnvolle Bandbreiten</li>
|
||
<li><strong>Eingebaute Unterstützung</strong> — Hinweise, Aufgabenpfade, Reflexionsimpulse</li>
|
||
<li><strong>Curriculare Passung</strong> — kompatibel zu Lehrplan und Lernzielen</li>
|
||
<li><strong>Technische Zugänglichkeit</strong> — funktioniert auf Schulgeräten, barrierearm, ohne Login-Hürden</li>
|
||
<li><strong>Einbettbarkeit</strong> — eine Schulstunde lang sinnvoll, nicht zwingend ganze Wochen</li>
|
||
</ol>
|
||
<p>Daraus ableitbar: konkrete Checkliste für Lehrkräfte vor dem Einsatz.</p>
|
||
</section>
|
||
|
||
<!-- 28 CHECKLISTE -->
|
||
<section>
|
||
<h2>Praxis-Checkliste — vor dem Einsatz</h2>
|
||
<ul>
|
||
<li>Decke ich damit ein konkretes Lernziel ab — oder ist es Lückenfüller?</li>
|
||
<li>Kann ich die Simulation in 45 Minuten sinnvoll einbetten?</li>
|
||
<li>Habe ich Reflexionsfragen vorbereitet — vor, während, nach?</li>
|
||
<li>Welche Rolle nehme ich ein — Erklärerin, Begleiterin, Mitlernende?</li>
|
||
<li>Wie sichere ich Übertragung in andere Kontexte (Transferaufgabe)?</li>
|
||
<li>Was tue ich, wenn die Technik streikt? Plan B?</li>
|
||
</ul>
|
||
</section>
|
||
|
||
<!-- KAPITEL 8 -->
|
||
<section>
|
||
<h3>Kapitel 8 — Hürden</h3>
|
||
<h1>Herausforderungen<br>& Ausblick</h1>
|
||
</section>
|
||
|
||
<!-- 30 HERAUSFORDERUNGEN -->
|
||
<section>
|
||
<h2>Was wir nicht vergessen dürfen</h2>
|
||
<h3>Digitale Kluft</h3>
|
||
<ul>
|
||
<li>Nicht jede Schule, nicht jedes Kind hat geeignete Geräte</li>
|
||
<li>Internet-Bandbreite, Schul-Firewalls, BYOD vs. Klassensätze</li>
|
||
</ul>
|
||
<h3>Oberflächlichkeit & Modellgrenzen</h3>
|
||
<ul>
|
||
<li>Klicken ≠ Verstehen — ohne Reflexion bleibt es Beschäftigungstherapie</li>
|
||
<li>Simulationen sind Modelle — die Reduktion muss thematisiert werden</li>
|
||
</ul>
|
||
<h3>Lehrerfortbildung als Flaschenhals</h3>
|
||
<ul>
|
||
<li>Werkzeuge ohne Didaktisierung verfehlen den Effekt</li>
|
||
<li>Zeit für Vorbereitung muss eingeplant sein</li>
|
||
</ul>
|
||
<p>Dazu kommen Datenschutz und die Gefahr stiller Abhängigkeit von kommerziellen Plattformen.</p>
|
||
</section>
|
||
|
||
<!-- 31 AUSBLICK -->
|
||
<section>
|
||
<h2>Was die nächsten Jahre bringen</h2>
|
||
<h3>KI-gestützte adaptive Simulationen</h3>
|
||
<p>Schwierigkeit, Hilfen, Fragestellungen passen sich an Lernstand an — datenbasiert, in Echtzeit.</p>
|
||
<h3>Immersive Lernumgebungen</h3>
|
||
<p>VR/AR im Klassenzimmer — wenn Hardware und Bandbreite nachziehen. Großes Potenzial für räumliches Verständnis.</p>
|
||
<h3>Open Educational Resources</h3>
|
||
<p>Frei verfügbare, lehrplankonforme Simulationen — gemeinsam von Lehrkräften und Forschung gepflegt.</p>
|
||
<h3>Forschungsbedarf</h3>
|
||
<p>Langzeitstudien zur Wirkung, Transferleistung und Inklusion fehlen weitgehend.</p>
|
||
</section>
|
||
|
||
<!-- 32 EMPFEHLUNGEN -->
|
||
<section>
|
||
<h2>5 Empfehlungen für die Praxis</h2>
|
||
<ol>
|
||
<li><strong>Klein anfangen</strong> — eine Simulation pro Halbjahr, fundiert eingebettet</li>
|
||
<li><strong>Reflexion einplanen</strong> — vorher Hypothese, nachher Vergleich mit Realität</li>
|
||
<li><strong>Lernziele vor Werkzeug</strong> — nicht das Tool sucht das Lernziel, umgekehrt</li>
|
||
<li><strong>Mit Kolleg*innen teilen</strong> — Unterrichtsvorbereitung als kollegiale Arbeit</li>
|
||
<li><strong>Modellgrenzen explizit machen</strong> — Schüler*innen sollen lernen, einer Simulation zu misstrauen</li>
|
||
</ol>
|
||
</section>
|
||
|
||
<!-- 33 FAZIT -->
|
||
<section>
|
||
<h2>Die entscheidende Frage</h2>
|
||
<p>ist nicht <strong>ob</strong> wir Simulationen einsetzen —</p>
|
||
<p>sondern <strong>wofür</strong> und <strong>wie eingebettet</strong>.</p>
|
||
<p>Eine Simulation ohne Lernanlass ist Spielerei. Eine Simulation mit Reflexion ist eines der mächtigsten Werkzeuge, das die Geografie-Didaktik je hatte.</p>
|
||
</section>
|
||
|
||
<!-- 34 QUELLEN -->
|
||
<section>
|
||
<h2>Kernquellen</h2>
|
||
<p>Vollständig unter quellen-simulation.html</p>
|
||
<p>D'Angelo, C. et al. (2014). Computer-based simulations and student learning. <em>SRI International / Review.</em></p>
|
||
<p>Smetana, L. K. & Bell, R. L. (2012). Computer simulations to support science instruction. <em>International Journal of Science Education.</em></p>
|
||
<p>de Jong, T., Linn, M. C. & Zacharia, Z. (2013). Physical and virtual laboratories. <em>Science.</em></p>
|
||
<p>Vlachopoulos, D. & Makri, A. (2017). The effect of games and simulations on higher education. <em>IJET in Higher Ed.</em></p>
|
||
<p>Mayer, R. E. (2014). <em>The Cambridge Handbook of Multimedia Learning.</em></p>
|
||
<p>Sweller, J., Ayres, P. & Kalyuga, S. (2011). <em>Cognitive Load Theory.</em></p>
|
||
<p>BMBWF (2023). Lehrplan Geographie und wirtschaftliche Bildung. <em>BGBl. Österreich.</em></p>
|
||
</section>
|
||
|
||
<!-- 35 DANKE -->
|
||
<section>
|
||
<h1>Danke.</h1>
|
||
<p>Fragen & Diskussion</p>
|
||
<p>Artikel & Quellenverzeichnis: lernen-durch-simulation.html · quellen-simulation.html</p>
|
||
<p>Thomas Schroffenegger · GeoGraSim · Sekundarstufe I · 2026</p>
|
||
</section>
|
||
|
||
</div><!-- /slides -->
|
||
</div><!-- /reveal -->
|
||
|
||
<!-- Home Button -->
|
||
<a class="home-btn" id="home-btn" href="../index.html" title="Zurück zum Artikel">⌂</a>
|
||
|
||
<!-- Panels -->
|
||
<div id="panel-layout" class="ui-panel">
|
||
<div class="panel-title">Design-Variante — Text immer fix oben links</div>
|
||
<div class="layout-opts">
|
||
<button class="layout-opt" id="lopt-rein" onclick="setLayout('rein')">
|
||
<div class="lo-icon">▭</div>
|
||
<div class="lo-name">Rein</div>
|
||
<div class="lo-desc">Kein Bild, klarer Hintergrund</div>
|
||
</button>
|
||
<button class="layout-opt" id="lopt-gradient" onclick="setLayout('gradient')">
|
||
<div class="lo-icon">◁▨</div>
|
||
<div class="lo-name">Verlauf</div>
|
||
<div class="lo-desc">Bild blendet rechts ein</div>
|
||
</button>
|
||
<button class="layout-opt" id="lopt-bg" onclick="setLayout('bg')">
|
||
<div class="lo-icon">▨</div>
|
||
<div class="lo-name">Hintergrund</div>
|
||
<div class="lo-desc">Bild blass dahinter</div>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="panel-font" class="ui-panel">
|
||
<div class="panel-title">Schriftstil</div>
|
||
<div class="font-opts" id="font-opts-list"></div>
|
||
</div>
|
||
|
||
<div id="panel-color" class="ui-panel">
|
||
<div class="panel-title">Hintergrundfarbe — aktuelle Folie</div>
|
||
<div class="color-swatches" id="color-swatches"></div>
|
||
<div class="color-row">
|
||
<input type="color" id="custom-color-input" value="#163374" oninput="applySlideColor(this.value)"/>
|
||
<label>Eigene Farbe</label>
|
||
</div>
|
||
<button class="panel-btn danger" onclick="clearSlideColor()">Farbe entfernen</button>
|
||
</div>
|
||
|
||
<!-- FAB Cluster — standardmäßig eingeklappt -->
|
||
<div id="fab-cluster">
|
||
<button class="fab" id="fab-toggle" title="Werkzeuge" onclick="toggleFabCluster()">⚙</button>
|
||
<div id="fab-tools">
|
||
<a class="fab" id="stil-btn" href="stile.html" title="Bildstil">◈</a>
|
||
<button class="fab" id="img-btn" title="Alle Folien generieren" onclick="generateAllImages()">✦</button>
|
||
<button class="fab" id="regen-btn" title="Nur diese Folie" onclick="regenCurrentSlide()">◎</button>
|
||
<button class="fab" id="layout-btn" title="Design-Variante" onclick="togglePanel('layout')">⊞</button>
|
||
<button class="fab" id="font-btn" title="Schriftstil" onclick="togglePanel('font')">Aa</button>
|
||
<button class="fab" id="color-btn" title="Farbe" onclick="togglePanel('color')">◉</button>
|
||
<button class="fab" id="save-btn" title="Speichern" onclick="saveAllSettings()">⊡</button>
|
||
<button class="fab" id="deploy-btn" title="Deployment-ZIP erstellen" onclick="buildDeployment()">⬇</button>
|
||
<button class="fab" id="pptx-btn" title="PowerPoint exportieren" onclick="exportPPTX()">⬇P</button>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Fixed Footer Bar -->
|
||
<div id="slide-footer-bar">
|
||
<svg id="footer-logo" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true"><path d="M8 15c4.418 0 8-3.134 8-7s-3.582-7-8-7-8 3.134-8 7c0 1.76.743 3.37 1.97 4.6-.097 1.016-.417 2.13-.771 2.966-.079.186.074.394.273.362 2.256-.37 3.597-.938 4.18-1.234A9 9 0 0 0 8 15m0-9.007c1.664-1.711 5.825 1.283 0 5.132-5.825-3.85-1.664-6.843 0-5.132"/></svg>
|
||
<span id="footer-num"></span>
|
||
<span id="footer-clock"></span>
|
||
</div>
|
||
|
||
<!-- Toast notification -->
|
||
<div id="img-toast"></div>
|
||
|
||
<script src="https://cdn.jsdelivr.net/npm/reveal.js@5.1.0/dist/reveal.js"></script>
|
||
<script>
|
||
Reveal.initialize({
|
||
hash: true,
|
||
transition: 'fade',
|
||
transitionSpeed: 'fast',
|
||
controls: true,
|
||
progress: true,
|
||
center: false,
|
||
slideNumber: false,
|
||
overview: true,
|
||
keyboard: true,
|
||
touch: true,
|
||
width: 1280,
|
||
height: 720,
|
||
margin: 0.10,
|
||
minScale: 0.2,
|
||
maxScale: 2.0,
|
||
plugins: []
|
||
});
|
||
|
||
// ── Footer bar ──
|
||
const homeBtn = document.getElementById('home-btn');
|
||
const imgBtn = document.getElementById('img-btn');
|
||
const stilBtn = document.getElementById('stil-btn');
|
||
const footerBar = document.getElementById('slide-footer-bar');
|
||
const footerNum = document.getElementById('footer-num');
|
||
const footerClk = document.getElementById('footer-clock');
|
||
var totalSlides = 0;
|
||
|
||
(function() {
|
||
var sn = localStorage.getItem('fal_presentation_style_name');
|
||
if (sn) imgBtn.title = 'KI-Bilder generieren · Stil: ' + sn;
|
||
})();
|
||
|
||
function isDarkSlide(slide) {
|
||
if (!slide) return false;
|
||
return slide.classList.contains('chapter-slide') || slide.classList.contains('title-slide');
|
||
}
|
||
|
||
function updateFooter() {
|
||
const slide = Reveal.getCurrentSlide();
|
||
const idx = Reveal.getState().indexh + 1;
|
||
const dark = isDarkSlide(slide);
|
||
if (dark) {
|
||
footerBar.classList.add('bar-light');
|
||
homeBtn.classList.remove('light');
|
||
imgBtn.classList.remove('light');
|
||
stilBtn.classList.remove('light');
|
||
} else {
|
||
footerBar.classList.remove('bar-light');
|
||
homeBtn.classList.add('light');
|
||
imgBtn.classList.add('light');
|
||
stilBtn.classList.add('light');
|
||
}
|
||
if (totalSlides > 0) footerNum.textContent = idx + ' / ' + totalSlides;
|
||
}
|
||
|
||
function updateClock() {
|
||
var now = new Date();
|
||
footerClk.textContent =
|
||
String(now.getHours()).padStart(2,'0') + ':' +
|
||
String(now.getMinutes()).padStart(2,'0') + ':' +
|
||
String(now.getSeconds()).padStart(2,'0');
|
||
}
|
||
setInterval(updateClock, 1000);
|
||
updateClock();
|
||
|
||
Reveal.on('slidechanged', updateFooter);
|
||
Reveal.on('ready', function() {
|
||
totalSlides = Reveal.getTotalSlides();
|
||
updateFooter();
|
||
setTimeout(_restoreCachedBackgrounds, 300);
|
||
if (window.renderMathInElement) {
|
||
renderMathInElement(document.body, {
|
||
delimiters: [{left:'$$',right:'$$',display:true},{left:'$',right:'$',display:false}],
|
||
throwOnError: false
|
||
});
|
||
}
|
||
});
|
||
|
||
// ══════════════════════════════════════════════════════════════════
|
||
// KI-BILDGENERIERUNG (fal.ai Flux)
|
||
// ══════════════════════════════════════════════════════════════════
|
||
var _LS_KEY = 'fal_presentation_style';
|
||
|
||
// Visueller Rahmenstil: technische Blaupause / Blueprint-Ästhetik
|
||
// Wird durch stile.html überschrieben falls der User einen Stil wählt.
|
||
var _DEFAULT_STYLE = "precise engineering schematic illustration, fine clean lines on dark navy blue " +
|
||
"background, schematic diagram, technical drawing aesthetic, no text labels, no numbers, no letters, " +
|
||
"ultra wide 16:9 format, elegant minimal composition";
|
||
var IMG_STYLE = localStorage.getItem(_LS_KEY + '_prompt') || _DEFAULT_STYLE;
|
||
|
||
var _imgGenerating = false;
|
||
var _SLIDE_CACHE_KEY = 'fal_slide_bg_v4';
|
||
var _SLIDE_CACHE_TTL = 55 * 60 * 1000;
|
||
|
||
function _slideCacheSet(idx, url) {
|
||
try {
|
||
var c = JSON.parse(localStorage.getItem(_SLIDE_CACHE_KEY) || '{}');
|
||
c['s' + idx] = { url: url, ts: Date.now() };
|
||
localStorage.setItem(_SLIDE_CACHE_KEY, JSON.stringify(c));
|
||
} catch(e) {}
|
||
}
|
||
function _slideCacheGet(idx) {
|
||
try {
|
||
var c = JSON.parse(localStorage.getItem(_SLIDE_CACHE_KEY) || '{}');
|
||
var e = c['s' + idx];
|
||
if (!e || Date.now() - e.ts > _SLIDE_CACHE_TTL) return null;
|
||
return e.url;
|
||
} catch(e) { return null; }
|
||
}
|
||
|
||
function _applyBackground(section, imageUrl) {
|
||
section.setAttribute('data-background-image', imageUrl);
|
||
section.setAttribute('data-background-opacity', '0.18');
|
||
section.setAttribute('data-background-size', 'cover');
|
||
section.setAttribute('data-background-position', 'center');
|
||
Reveal.sync();
|
||
}
|
||
|
||
function _restoreCachedBackgrounds() {
|
||
if (_currentLayout === 'rein') return;
|
||
var sects = [...document.querySelectorAll('.reveal .slides > section')];
|
||
var anyRestored = false;
|
||
sects.forEach(function(s, idx) {
|
||
var url = _slideCacheGet(idx);
|
||
if (url) { _applyBackground(s, url); anyRestored = true; }
|
||
});
|
||
if (anyRestored) setTimeout(function() { Reveal.sync(); }, 1200);
|
||
}
|
||
|
||
function _toast(msg, ms) {
|
||
var t = document.getElementById('img-toast');
|
||
t.textContent = msg;
|
||
t.style.opacity = '1';
|
||
setTimeout(function() { t.style.opacity = '0'; }, ms || 2500);
|
||
}
|
||
|
||
async function _fetchImage(prompt) {
|
||
var key = window.FAL_KEY;
|
||
if (!key) return null;
|
||
try {
|
||
var res = await fetch('https://fal.run/fal-ai/flux/schnell', {
|
||
method: 'POST',
|
||
headers: { 'Authorization': 'Key ' + key, 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
prompt: prompt + ', ' + IMG_STYLE + ', no text, no letters, no numbers',
|
||
image_size: 'landscape_16_9',
|
||
num_inference_steps: 4,
|
||
num_images: 1,
|
||
enable_safety_checker: true
|
||
})
|
||
});
|
||
var data = await res.json();
|
||
if (data.detail) { console.warn('fal.ai:', data.detail); return null; }
|
||
return (data.images && data.images[0]) ? data.images[0].url : null;
|
||
} catch(e) { console.warn('fal.ai Fehler:', e); return null; }
|
||
}
|
||
|
||
// ── Thematische Bildbeschreibung pro Folie (Blueprint-Stil) ──
|
||
// Motiv passend zum Slide-Inhalt, dargestellt als technische Blaupause / Schemazeichnung.
|
||
// Kein Foto, kein Text, keine Buchstaben im Bild.
|
||
function _slideVisual(section) {
|
||
var h1 = (section.querySelector('h1') || {}).textContent || '';
|
||
var h2 = (section.querySelector('h2') || {}).textContent || '';
|
||
var h3 = (section.querySelector('h3') || {}).textContent || '';
|
||
var txt = (h1 + ' ' + h2 + ' ' + h3).toLowerCase();
|
||
|
||
if (/lernen durch|lernen.*simulation|titel|sekundarstufe i.*2026/.test(txt))
|
||
return "schematic illustration of a glowing tablet on a wooden desk showing a stylised landscape simulation with mountains, river and clouds, soft light radiating from the screen, dark navy blue background, fine white and gold lines";
|
||
|
||
if (/befund.*30|effektstärke|simulationen wirken/.test(txt))
|
||
return "schematic chart of an upward growth curve and bell distribution, abstract diagram of effect sizes, fine white and gold lines on dark navy blue background, no text no numbers";
|
||
|
||
if (/warum simulationen|geografieunterricht/.test(txt))
|
||
return "schematic illustration of a globe with three smaller insets showing climate, city and river, all connected with thin guide lines, white lines on dark navy blue, technical diagram style";
|
||
|
||
if (/überblick|aufbau/.test(txt))
|
||
return "top-down technical grid schematic of a presentation outline, two columns of stacked rectangular sections, structured plan view, fine white lines on dark navy";
|
||
|
||
if (/was ist eine simulation|arbeitsdefinition/.test(txt))
|
||
return "schematic exploded view of three layered components labelled abstractly as model, rules, interaction, fine white lines on dark navy blue, technical diagram";
|
||
|
||
if (/lerntheor|konstruktiv|cognitive load|multimedia/.test(txt))
|
||
return "schematic diagram of a brain with three interconnected modules and arrows, neuroscience inspired technical drawing, fine white lines and gold accents on dark navy blue";
|
||
|
||
if (/stand der forschung|forschungsstand|publikation/.test(txt))
|
||
return "schematic stack of academic papers and journals with thin annotation lines, library archive cross-section, fine white lines on dark navy blue";
|
||
|
||
if (/welche arten|typen|klassifikation/.test(txt))
|
||
return "schematic illustration of three nested concentric panels showing increasing interactivity, abstract diagram of classification, fine white lines on dark navy blue";
|
||
|
||
if (/phet|serious|virtuelle labor|vr.*ar|vier.*familien/.test(txt))
|
||
return "schematic four-quadrant grid each containing an abstract icon: laboratory flask, game controller, vr headset and network nodes, fine white lines on dark navy blue, technical diagram";
|
||
|
||
if (/wirksamkeit|meta-analyt|d.*angelo|smetana/.test(txt))
|
||
return "schematic diagram of a magnifying glass over a bar chart, technical scientific illustration, fine white lines and gold accents on dark navy blue";
|
||
|
||
if (/cognitive outcome|affektiv|motivational|outcome/.test(txt))
|
||
return "schematic of a brain on the left and a glowing heart on the right connected by thin guide lines, technical anatomical diagram, fine white lines on dark navy blue";
|
||
|
||
if (/transfer|virtuell.*real|hybrid/.test(txt))
|
||
return "schematic of two overlapping ring shapes with a bridge line between them, technical diagram showing connection between virtual and real, fine white and gold lines on dark navy blue";
|
||
|
||
if (/gestaltung|prinzipien|ausmacht/.test(txt))
|
||
return "schematic blueprint of an architect's drafting board with precise tools, t-square and ruler, fine white lines on dark navy blue, design diagram style";
|
||
|
||
if (/cognitive load.*hürde|extraneous|germane/.test(txt))
|
||
return "schematic of a balance scale with stylised weights labelled abstractly, technical diagram of cognitive balance, fine white lines on dark navy blue";
|
||
|
||
if (/lehrperson|lernbegleit|wissensvermittler/.test(txt))
|
||
return "schematic silhouette of a teacher figure with thin guide lines connecting to abstract student figures, technical diagram, fine white lines on dark navy blue";
|
||
|
||
if (/dreieck|triangle|lehrperson.*simulation/.test(txt))
|
||
return "schematic of an equilateral triangle with three labelled vertices connected by thin lines, abstract technical diagram showing three-way relationship, fine white and gold lines on dark navy blue";
|
||
|
||
if (/anwendung.*gw|geografie.*profitiert|räumliches denken/.test(txt))
|
||
return "schematic of a stylised globe with multiple cross-section layers showing terrain, atmosphere and ocean, technical earth diagram, fine white lines on dark navy blue";
|
||
|
||
if (/anwendungsfeld|klimawandel|naturgefahr|stadt/.test(txt))
|
||
return "schematic three-panel diagram showing weather front clouds, mountain landslide and city grid, technical cross-section, fine white lines on dark navy blue";
|
||
|
||
if (/lehrplan|österreich/.test(txt))
|
||
return "schematic of an open book with chapter markers and a stylised austrian map outline, technical diagram, fine white lines on dark navy blue";
|
||
|
||
if (/qualität|sechs dimension|qualitäts/.test(txt))
|
||
return "schematic of a hexagonal diagram with six radial spokes labelled abstractly, quality framework illustration, fine white and gold lines on dark navy blue";
|
||
|
||
if (/checkliste|praxis-checkliste/.test(txt))
|
||
return "schematic of a checklist clipboard with thin checkmark lines, technical illustration, fine white lines on dark navy blue";
|
||
|
||
if (/herausforderung|hürde|nicht vergessen|digitale kluft/.test(txt))
|
||
return "schematic of a structure with thin fracture lines running through it, structural diagram of obstacles, fine white lines and red accents on dark navy blue";
|
||
|
||
if (/ausblick|nächsten jahre|adaptive|immersiv|oer/.test(txt))
|
||
return "schematic of a telescope cross-section with light rays and a glowing horizon, technical optical diagram, fine white and gold lines on dark navy blue";
|
||
|
||
if (/empfehlung|praxis/.test(txt))
|
||
return "schematic of a clipboard with five numbered annotation lines, technical checklist illustration, fine white and gold lines on dark navy blue";
|
||
|
||
if (/entscheidend.*frage|fazit|wofür|eingebettet/.test(txt))
|
||
return "schematic of a key inserted into a lock cross-section, abstract technical diagram, fine white and gold lines on dark navy blue";
|
||
|
||
if (/quellen|literatur|kernquellen/.test(txt))
|
||
return "schematic cross-section of a library bookshelf with stacked volumes, technical drawing, fine white lines on dark navy blue";
|
||
|
||
if (/danke|diskussion/.test(txt))
|
||
return "schematic of a stylised circular rose window divided into equal segments radiating from center, fine white lines on dark navy blue, elegant symmetry";
|
||
|
||
return "schematic illustration of a glowing tablet showing an abstract landscape with mountains and a river simulation, fine white and gold lines on dark navy blue background";
|
||
}
|
||
|
||
window.generateAllImages = async function() {
|
||
if (_imgGenerating) return;
|
||
if (!window.FAL_KEY) { alert('Kein API-Key.\nBitte in „API Key.js" eintragen.'); return; }
|
||
IMG_STYLE = localStorage.getItem(_LS_KEY + '_prompt') || _DEFAULT_STYLE;
|
||
_imgGenerating = true;
|
||
imgBtn.classList.add('generating');
|
||
|
||
var allSects = [...document.querySelectorAll('.reveal .slides > section')];
|
||
var total = allSects.length;
|
||
var done = 0;
|
||
|
||
_toast('Generiere ' + total + ' Bilder — Navigation weiter möglich ✓', 3500);
|
||
|
||
for (var i = 0; i < allSects.length; i++) {
|
||
var section = allSects[i];
|
||
done++;
|
||
imgBtn.textContent = done + '/' + total;
|
||
|
||
var visual = _slideVisual(section);
|
||
var url = await _fetchImage(visual);
|
||
if (url) {
|
||
_slideCacheSet(i, url);
|
||
_applyBackground(section, url);
|
||
}
|
||
}
|
||
|
||
_imgGenerating = false;
|
||
imgBtn.classList.remove('generating');
|
||
imgBtn.textContent = '↺';
|
||
imgBtn.title = 'Bilder neu generieren';
|
||
_toast('Fertig — alle Bilder generiert ✓', 3000);
|
||
};
|
||
|
||
// ── Per-Folie neu generieren ──
|
||
window.regenCurrentSlide = async function() {
|
||
if (_imgGenerating) return;
|
||
if (!window.FAL_KEY) { alert('Kein API-Key.\nBitte in „API Key.js" eintragen.'); return; }
|
||
IMG_STYLE = localStorage.getItem(_LS_KEY + '_prompt') || _DEFAULT_STYLE;
|
||
var allSects = [...document.querySelectorAll('.reveal .slides > section')];
|
||
var section = Reveal.getCurrentSlide();
|
||
var idx = allSects.indexOf(section);
|
||
document.getElementById('regen-btn').textContent = '…';
|
||
var url = await _fetchImage(_slideVisual(section));
|
||
if (url) {
|
||
_slideCacheSet(idx, url);
|
||
_applyBackground(section, url);
|
||
_toast('Bild aktualisiert ✓', 2000);
|
||
}
|
||
document.getElementById('regen-btn').textContent = '◎';
|
||
};
|
||
|
||
// ══ LAYOUT-VARIANTEN ══
|
||
// Drei Modi — Text sitzt immer fix, Bilder sind reine Dekoration.
|
||
// rein: Kein Bild, klarer Hintergrund
|
||
// gradient: Bild von rechts einblendend (Gradient-Overlay schützt Text)
|
||
// bg: Bild blass im gesamten Hintergrund
|
||
var _currentLayout = localStorage.getItem('pres_layout_v1') || 'rein';
|
||
|
||
function _bgOpacityForLayout() {
|
||
return _currentLayout === 'gradient' ? '1' : '0.18';
|
||
}
|
||
|
||
window.setLayout = function(name) {
|
||
_currentLayout = name;
|
||
localStorage.setItem('pres_layout_v1', name);
|
||
|
||
var allSects = [...document.querySelectorAll('.reveal .slides > section')];
|
||
var slidesEl = document.querySelector('.reveal .slides');
|
||
|
||
// CSS-Klasse für mask-image auf .slide-background-image + .slides inline background
|
||
if (slidesEl) slidesEl.style.background = '';
|
||
|
||
if (name === 'rein') {
|
||
allSects.forEach(function(s) { s.removeAttribute('data-background-image'); });
|
||
Reveal.sync();
|
||
} else {
|
||
// gradient + bg: _applyBackground-Überschreibung kümmert sich um Canvas-Verarbeitung
|
||
allSects.forEach(function(s, idx) {
|
||
var url = _slideCacheGet(idx);
|
||
if (url) _applyBackground(s, url);
|
||
});
|
||
// Finales Sync nach async Canvas-Verarbeitung
|
||
setTimeout(function() { Reveal.sync(); }, 1200);
|
||
}
|
||
|
||
// Panel-Buttons markieren
|
||
['rein','gradient','bg'].forEach(function(id) {
|
||
var el = document.getElementById('lopt-' + id);
|
||
if (el) el.classList.toggle('active', id === name);
|
||
});
|
||
closePanel('layout');
|
||
};
|
||
|
||
function _applyStoredLayout() {
|
||
setLayout(_currentLayout);
|
||
}
|
||
|
||
// ── Canvas-Gradient: weiß links → voll rechts (Pixelebene, kein CSS-Layer-Problem) ──
|
||
function _processImageWithGradient(imageUrl) {
|
||
return new Promise(function(resolve) {
|
||
var img = new Image();
|
||
img.crossOrigin = 'anonymous';
|
||
img.onload = function() {
|
||
try {
|
||
var W = 1280, H = 720;
|
||
var canvas = document.createElement('canvas');
|
||
canvas.width = W; canvas.height = H;
|
||
var ctx = canvas.getContext('2d');
|
||
// Bild skaliert auf Canvas zeichnen
|
||
ctx.drawImage(img, 0, 0, W, H);
|
||
// Weißen Verlauf drüberlegen: links deckend → rechts transparent
|
||
var grad = ctx.createLinearGradient(0, 0, W, 0);
|
||
grad.addColorStop(0, 'rgba(255,255,255,1)');
|
||
grad.addColorStop(0.50, 'rgba(255,255,255,1)');
|
||
grad.addColorStop(0.65, 'rgba(255,255,255,0.80)');
|
||
grad.addColorStop(0.78, 'rgba(255,255,255,0.45)');
|
||
grad.addColorStop(0.90, 'rgba(255,255,255,0.12)');
|
||
grad.addColorStop(1, 'rgba(255,255,255,0)');
|
||
ctx.fillStyle = grad;
|
||
ctx.fillRect(0, 0, W, H);
|
||
resolve(canvas.toDataURL('image/jpeg', 0.93));
|
||
} catch(e) {
|
||
// CORS-Taint — Original-URL als Fallback
|
||
console.warn('Canvas CORS-Fehler, Fallback auf Original:', e);
|
||
resolve(imageUrl);
|
||
}
|
||
};
|
||
img.onerror = function() { resolve(imageUrl); };
|
||
img.src = imageUrl;
|
||
});
|
||
}
|
||
|
||
// _applyBackground berücksichtigt den aktuellen Layout-Modus
|
||
var _origApplyBackground = _applyBackground;
|
||
_applyBackground = async function(section, imageUrl) {
|
||
if (_currentLayout === 'rein') return;
|
||
var url = imageUrl;
|
||
if (_currentLayout === 'gradient') {
|
||
url = await _processImageWithGradient(imageUrl);
|
||
}
|
||
var opacity = _currentLayout === 'gradient' ? '1' : '0.18';
|
||
section.setAttribute('data-background-image', url);
|
||
section.setAttribute('data-background-opacity', opacity);
|
||
section.setAttribute('data-background-size', 'cover');
|
||
section.setAttribute('data-background-position', 'center');
|
||
Reveal.sync();
|
||
};
|
||
|
||
// ══ SCHRIFTSTILE ══
|
||
var FONT_THEMES = [
|
||
{
|
||
id: 'system',
|
||
name: 'System',
|
||
pair: 'system-ui — neutral',
|
||
h: 'system-ui, -apple-system, sans-serif',
|
||
b: 'system-ui, -apple-system, sans-serif'
|
||
},
|
||
{
|
||
id: 'fraunces',
|
||
name: 'Fraunces',
|
||
pair: 'Fraunces + Inter — elegant Serif',
|
||
h: "'Fraunces', Georgia, serif",
|
||
b: "'Inter', system-ui, sans-serif"
|
||
},
|
||
{
|
||
id: 'space',
|
||
name: 'Space Grotesk',
|
||
pair: 'Space Grotesk — geometrisch',
|
||
h: "'Space Grotesk', system-ui, sans-serif",
|
||
b: "'Space Grotesk', system-ui, sans-serif"
|
||
},
|
||
{
|
||
id: 'syne',
|
||
name: 'Syne',
|
||
pair: 'Syne — Graphic Display',
|
||
h: "'Syne', system-ui, sans-serif",
|
||
b: "'Syne', system-ui, sans-serif"
|
||
},
|
||
{
|
||
id: 'bricolage',
|
||
name: 'Bricolage',
|
||
pair: 'Bricolage Grotesque — zeitgenössisch',
|
||
h: "'Bricolage Grotesque', system-ui, sans-serif",
|
||
b: "'Bricolage Grotesque', system-ui, sans-serif"
|
||
},
|
||
{
|
||
id: 'barlow',
|
||
name: 'Barlow Condensed',
|
||
pair: 'Barlow Condensed — Lettering-Style',
|
||
h: "'Barlow Condensed', system-ui, sans-serif",
|
||
b: "'Inter', system-ui, sans-serif"
|
||
},
|
||
{
|
||
id: 'caveat',
|
||
name: 'Caveat Brush',
|
||
pair: 'Caveat Brush — Hand Lettering',
|
||
h: "'Caveat Brush', cursive",
|
||
b: "'Inter', system-ui, sans-serif"
|
||
},
|
||
{
|
||
id: 'satisfy',
|
||
name: 'Satisfy',
|
||
pair: 'Satisfy — Brush Script',
|
||
h: "'Satisfy', cursive",
|
||
b: "'Inter', system-ui, sans-serif"
|
||
}
|
||
];
|
||
|
||
var _currentFontId = (function() {
|
||
var stored = localStorage.getItem('pres_font_v1') || 'system';
|
||
return FONT_THEMES.some(function(f){ return f.id === stored; }) ? stored : 'system';
|
||
})();
|
||
|
||
function _renderFontPanel() {
|
||
var list = document.getElementById('font-opts-list');
|
||
if (!list) return;
|
||
list.innerHTML = '';
|
||
FONT_THEMES.forEach(function(t) {
|
||
var div = document.createElement('button');
|
||
div.className = 'font-opt' + (t.id === _currentFontId ? ' active' : '');
|
||
div.id = 'fopt-' + t.id;
|
||
div.onclick = function() { applyFontTheme(t.id); };
|
||
div.innerHTML =
|
||
'<span class="fo-sample" style="font-family:' + t.h + ';font-weight:700">Ag</span>' +
|
||
'<span class="fo-info"><span class="fo-name">' + t.name + '</span>' +
|
||
'<span class="fo-pair" style="display:block">' + t.pair + '</span></span>';
|
||
list.appendChild(div);
|
||
});
|
||
}
|
||
|
||
window.applyFontTheme = function(id) {
|
||
var t = FONT_THEMES.find(function(f){ return f.id === id; });
|
||
if (!t) return;
|
||
_currentFontId = id;
|
||
localStorage.setItem('pres_font_v1', id);
|
||
var style = document.getElementById('font-theme-style') || document.createElement('style');
|
||
style.id = 'font-theme-style';
|
||
style.textContent =
|
||
'.reveal h1, .reveal h2 { font-family: ' + t.h + ' !important; }' +
|
||
'.reveal, .reveal p, .reveal li, .reveal h3 { font-family: ' + t.b + ' !important; }';
|
||
document.head.appendChild(style);
|
||
// Update active state
|
||
document.querySelectorAll('.font-opt').forEach(function(el) {
|
||
el.classList.toggle('active', el.id === 'fopt-' + id);
|
||
});
|
||
closePanel('font');
|
||
_toast(t.name + ' aktiviert', 1800);
|
||
};
|
||
|
||
// ══ HINTERGRUNDFARBE ══
|
||
var _COLORS_KEY = 'pres_colors_v1';
|
||
var _COLOR_PRESETS = [
|
||
'#ffffff','#f8f7f4','#f0f4fd','#e8f5ee','#fdf6e3',
|
||
'#0c0f18','#163374','#1a3a1a','#2d2d2d','#f5e6d3'
|
||
];
|
||
|
||
function _renderColorPanel() {
|
||
var box = document.getElementById('color-swatches');
|
||
if (!box) return;
|
||
box.innerHTML = '';
|
||
_COLOR_PRESETS.forEach(function(c) {
|
||
var s = document.createElement('div');
|
||
s.className = 'color-swatch';
|
||
s.style.background = c;
|
||
s.style.border = c === '#ffffff' ? '2px solid #ddd' : '2px solid transparent';
|
||
s.title = c;
|
||
s.onclick = function() { applySlideColor(c); };
|
||
box.appendChild(s);
|
||
});
|
||
}
|
||
|
||
window.applySlideColor = function(color) {
|
||
var section = Reveal.getCurrentSlide();
|
||
var allSects = [...document.querySelectorAll('.reveal .slides > section')];
|
||
var idx = allSects.indexOf(section);
|
||
section.setAttribute('data-background-color', color);
|
||
try {
|
||
var c = JSON.parse(localStorage.getItem(_COLORS_KEY) || '{}');
|
||
c['s' + idx] = color;
|
||
localStorage.setItem(_COLORS_KEY, JSON.stringify(c));
|
||
} catch(e) {}
|
||
Reveal.sync();
|
||
};
|
||
|
||
window.clearSlideColor = function() {
|
||
var section = Reveal.getCurrentSlide();
|
||
var allSects = [...document.querySelectorAll('.reveal .slides > section')];
|
||
var idx = allSects.indexOf(section);
|
||
section.removeAttribute('data-background-color');
|
||
try {
|
||
var c = JSON.parse(localStorage.getItem(_COLORS_KEY) || '{}');
|
||
delete c['s' + idx];
|
||
localStorage.setItem(_COLORS_KEY, JSON.stringify(c));
|
||
} catch(e) {}
|
||
Reveal.sync();
|
||
};
|
||
|
||
function _restoreSlideColors() {
|
||
try {
|
||
var c = JSON.parse(localStorage.getItem(_COLORS_KEY) || '{}');
|
||
var sects = [...document.querySelectorAll('.reveal .slides > section')];
|
||
Object.keys(c).forEach(function(k) {
|
||
var idx = parseInt(k.slice(1));
|
||
var color = c[k];
|
||
if (sects[idx]) {
|
||
sects[idx].setAttribute('data-background-color', color);
|
||
}
|
||
});
|
||
if (Object.keys(c).length) Reveal.sync();
|
||
} catch(e) {}
|
||
}
|
||
|
||
// ══ FAB TOGGLE ══
|
||
var _fabOpen = false;
|
||
window.toggleFabCluster = function() {
|
||
_fabOpen = !_fabOpen;
|
||
document.getElementById('fab-cluster').classList.toggle('open', _fabOpen);
|
||
document.getElementById('fab-toggle').textContent = _fabOpen ? '✕' : '⚙';
|
||
if (!_fabOpen && _openPanel) closePanel(_openPanel);
|
||
};
|
||
|
||
// ══ PANELS ══
|
||
var _openPanel = null;
|
||
window.togglePanel = function(name) {
|
||
var el = document.getElementById('panel-' + name);
|
||
if (!el) return;
|
||
if (_openPanel && _openPanel !== name) {
|
||
var prev = document.getElementById('panel-' + _openPanel);
|
||
if (prev) prev.classList.remove('open');
|
||
}
|
||
el.classList.toggle('open');
|
||
_openPanel = el.classList.contains('open') ? name : null;
|
||
};
|
||
window.closePanel = function(name) {
|
||
var el = document.getElementById('panel-' + name);
|
||
if (el) el.classList.remove('open');
|
||
if (_openPanel === name) _openPanel = null;
|
||
};
|
||
// Close panels + fab on outside click
|
||
document.addEventListener('click', function(e) {
|
||
var inFab = e.target.closest('#fab-cluster');
|
||
var inPanel = e.target.closest('.ui-panel');
|
||
var inHome = e.target.closest('.home-btn');
|
||
if (_openPanel && !inPanel && !inFab && !inHome) closePanel(_openPanel);
|
||
if (_fabOpen && !inFab && !inPanel) {
|
||
_fabOpen = false;
|
||
document.getElementById('fab-cluster').classList.remove('open');
|
||
document.getElementById('fab-toggle').textContent = '⚙';
|
||
}
|
||
});
|
||
|
||
// ══ SPEICHERN ══
|
||
window.saveAllSettings = function() {
|
||
var settings = {
|
||
layout: _currentLayout,
|
||
font: _currentFontId,
|
||
styleId: localStorage.getItem('fal_presentation_style_id') || '',
|
||
stylePrompt: localStorage.getItem('fal_presentation_style_prompt') || '',
|
||
slideColors: JSON.parse(localStorage.getItem(_COLORS_KEY) || '{}'),
|
||
slideImages: JSON.parse(localStorage.getItem(_SLIDE_CACHE_KEY) || '{}'),
|
||
savedAt: new Date().toISOString()
|
||
};
|
||
// Download als JSON
|
||
var blob = new Blob([JSON.stringify(settings, null, 2)], { type: 'application/json' });
|
||
var a = document.createElement('a');
|
||
a.href = URL.createObjectURL(blob);
|
||
a.download = 'praesentation-einstellungen.json';
|
||
a.click();
|
||
_toast('Einstellungen gespeichert ✓', 2500);
|
||
};
|
||
|
||
// ══ INIT ══
|
||
Reveal.on('ready', function() {
|
||
_renderFontPanel();
|
||
_renderColorPanel();
|
||
setTimeout(function() {
|
||
_applyStoredLayout();
|
||
_restoreSlideColors();
|
||
applyFontTheme(_currentFontId);
|
||
}, 400);
|
||
});
|
||
|
||
// ══ DEPLOYMENT-EXPORT ══
|
||
// Erstellt ein ZIP mit statischer Präsentation (Bilder eingebettet, kein FAB),
|
||
// standalone.html, quellen.html und lokalen Schriften.
|
||
window.buildDeployment = async function() {
|
||
var deployBtn = document.getElementById('deploy-btn');
|
||
deployBtn.textContent = '…';
|
||
|
||
// JSZip dynamisch laden
|
||
if (!window.JSZip) {
|
||
await new Promise(function(resolve, reject) {
|
||
var s = document.createElement('script');
|
||
s.src = 'https://cdn.jsdelivr.net/npm/jszip@3.10.1/dist/jszip.min.js';
|
||
s.onload = resolve; s.onerror = reject;
|
||
document.head.appendChild(s);
|
||
});
|
||
}
|
||
|
||
var zip = new JSZip();
|
||
_toast('Deployment wird erstellt …', 10000);
|
||
|
||
// ── 1. Statische Präsentation ──
|
||
// Aktuellen DOM klonen, Werkzeuge entfernen
|
||
var clone = document.documentElement.cloneNode(true);
|
||
['#fab-cluster', '#panel-layout', '#panel-font', '#panel-color', '#img-toast'].forEach(function(sel) {
|
||
var el = clone.querySelector(sel); if (el) el.remove();
|
||
});
|
||
// API Key Script entfernen
|
||
clone.querySelectorAll('script').forEach(function(s) {
|
||
if (s.src && s.src.includes('API Key')) s.remove();
|
||
});
|
||
// Aktuelle Font-Theme-Styles als statisch einbetten (bereits im DOM)
|
||
zip.file('presentation/index.html', '<!DOCTYPE html>\n' + clone.outerHTML);
|
||
|
||
// ── 2. Schriften ──
|
||
var fontFiles = [
|
||
'fonts.css',
|
||
'barlow-condensed-600.woff2','barlow-condensed-700.woff2','barlow-condensed-800.woff2',
|
||
'bricolage-grotesque.woff2','caveat-brush.woff2','fraunces-normal.woff2','fraunces-italic.woff2',
|
||
'inter.woff2','satisfy.woff2','space-grotesk.woff2','syne.woff2',
|
||
'SpaceGrotesk-400.woff2','SpaceGrotesk-600.woff2','SpaceGrotesk-700.woff2',
|
||
'PlayfairDisplay-400.woff2','PlayfairDisplay-700.woff2','PlayfairDisplay-900.woff2'
|
||
];
|
||
for (var ff of fontFiles) {
|
||
try {
|
||
var r = await fetch('fonts/' + ff);
|
||
if (r.ok) zip.file('presentation/fonts/' + ff, await r.arrayBuffer());
|
||
} catch(e) {}
|
||
}
|
||
|
||
// ── 3. Artikel und Quellen ──
|
||
for (var pf of ['standalone.html', 'quellen.html']) {
|
||
try {
|
||
var r2 = await fetch('../' + pf);
|
||
if (r2.ok) zip.file(pf, await r2.text());
|
||
} catch(e) { console.warn('Nicht ladbar:', pf, e); }
|
||
}
|
||
|
||
// ── 4. Landingpage ──
|
||
var meta = document.title || 'Forschungsartikel';
|
||
zip.file('index.html', '<!DOCTYPE html>\n<html lang="de">\n<head>\n<meta charset="UTF-8"/>\n' +
|
||
'<meta name="viewport" content="width=device-width,initial-scale=1"/>\n' +
|
||
'<title>' + meta + '</title>\n' +
|
||
'<style>body{font-family:system-ui,sans-serif;max-width:680px;margin:4rem auto;padding:0 2rem;color:#222}' +
|
||
'h1{font-size:1.4rem;margin-bottom:.5rem}p{color:#666;margin-bottom:2rem}' +
|
||
'nav{display:flex;flex-direction:column;gap:.8rem}' +
|
||
'a{display:inline-block;padding:.7rem 1.2rem;background:#163374;color:#fff;text-decoration:none;border-radius:6px;width:fit-content}' +
|
||
'a:hover{background:#0f2456}</style>\n</head>\n<body>\n' +
|
||
'<h1>' + meta + '</h1>\n<p>Wähle einen Bereich:</p>\n<nav>\n' +
|
||
'<a href="standalone.html">📄 Artikel lesen</a>\n' +
|
||
'<a href="quellen.html">📚 Quelldatenbank</a>\n' +
|
||
'<a href="presentation/index.html">▶ Präsentation</a>\n' +
|
||
'</nav>\n</body>\n</html>');
|
||
|
||
// ── 5. ZIP herunterladen ──
|
||
var blob = await zip.generateAsync({ type: 'blob', compression: 'DEFLATE', compressionOptions: { level: 6 } });
|
||
var a = document.createElement('a');
|
||
a.href = URL.createObjectURL(blob);
|
||
a.download = 'deployment.zip';
|
||
a.click();
|
||
deployBtn.textContent = '⬇';
|
||
_toast('deployment.zip heruntergeladen ✓', 3000);
|
||
};
|
||
|
||
// ══ PPTX-EXPORT ══
|
||
// Erzeugt eine echte .pptx-Datei mit pptxgenjs — editierbar in PowerPoint/LibreOffice
|
||
window.exportPPTX = async function() {
|
||
var btn = document.getElementById('pptx-btn');
|
||
btn.textContent = '…';
|
||
_toast('PowerPoint wird erstellt …', 8000);
|
||
|
||
// pptxgenjs dynamisch laden
|
||
if (!window.PptxGenJS) {
|
||
await new Promise(function(resolve, reject) {
|
||
var s = document.createElement('script');
|
||
s.src = 'https://cdn.jsdelivr.net/npm/pptxgenjs@3.12.0/dist/pptxgen.bundle.js';
|
||
s.onload = resolve; s.onerror = reject;
|
||
document.head.appendChild(s);
|
||
});
|
||
}
|
||
|
||
var pptx = new PptxGenJS();
|
||
pptx.layout = 'LAYOUT_WIDE';
|
||
pptx.author = document.title || 'Forschungsartikel';
|
||
|
||
var sections = document.querySelectorAll('.reveal .slides > section');
|
||
|
||
for (var i = 0; i < sections.length; i++) {
|
||
var sec = sections[i];
|
||
var slide = pptx.addSlide();
|
||
|
||
// ── Hintergrundbild ──
|
||
var bgImg = sec.getAttribute('data-background-image');
|
||
var bgColor = sec.getAttribute('data-background-color');
|
||
var bgOpacity = parseFloat(sec.getAttribute('data-background-opacity') || '1');
|
||
|
||
if (bgImg) {
|
||
try {
|
||
var imgData = bgImg;
|
||
if (!bgImg.startsWith('data:')) {
|
||
imgData = await (async function(url) {
|
||
try {
|
||
var resp = await fetch(url);
|
||
var blob = await resp.blob();
|
||
return await new Promise(function(resolve) {
|
||
var reader = new FileReader();
|
||
reader.onloadend = function() { resolve(reader.result); };
|
||
reader.readAsDataURL(blob);
|
||
});
|
||
} catch(e) { return null; }
|
||
})(bgImg);
|
||
}
|
||
if (imgData) {
|
||
if (bgOpacity < 0.5) {
|
||
imgData = await (async function(dataUrl, opacity) {
|
||
return new Promise(function(resolve) {
|
||
var img = new Image();
|
||
img.onload = function() {
|
||
var c = document.createElement('canvas');
|
||
c.width = 1280; c.height = 720;
|
||
var ctx = c.getContext('2d');
|
||
ctx.fillStyle = '#fff';
|
||
ctx.fillRect(0, 0, 1280, 720);
|
||
ctx.globalAlpha = opacity;
|
||
ctx.drawImage(img, 0, 0, 1280, 720);
|
||
ctx.globalAlpha = 1;
|
||
resolve(c.toDataURL('image/jpeg', 0.92));
|
||
};
|
||
img.onerror = function() { resolve(dataUrl); };
|
||
img.src = dataUrl;
|
||
});
|
||
})(imgData, bgOpacity);
|
||
}
|
||
slide.background = { data: imgData };
|
||
} else {
|
||
slide.background = { color: bgColor ? bgColor.replace('#', '') : 'FFFFFF' };
|
||
}
|
||
} catch(e) {
|
||
slide.background = { color: 'FFFFFF' };
|
||
}
|
||
} else if (bgColor) {
|
||
slide.background = { color: bgColor.replace('#', '') };
|
||
} else {
|
||
slide.background = { color: 'FFFFFF' };
|
||
}
|
||
|
||
// ── Texte ──
|
||
var h1 = sec.querySelector('h1');
|
||
var h2 = sec.querySelector('h2');
|
||
var h3 = sec.querySelector('h3');
|
||
var pars = sec.querySelectorAll('p');
|
||
var lis = sec.querySelectorAll('li');
|
||
var yPos = 0.5;
|
||
|
||
if (h3) {
|
||
slide.addText(h3.textContent.trim(), {
|
||
x: 0.6, y: yPos, w: '80%', h: 0.4,
|
||
fontSize: 11, color: '888888', fontFace: 'Arial',
|
||
bold: true, charSpacing: 3, isTextBox: true
|
||
});
|
||
yPos += 0.45;
|
||
}
|
||
if (h1) {
|
||
slide.addText(h1.textContent.trim(), {
|
||
x: 0.6, y: yPos, w: '55%', h: 1.0,
|
||
fontSize: 32, color: '111111', fontFace: 'Arial',
|
||
bold: true, isTextBox: true, shrinkText: true
|
||
});
|
||
yPos += 1.1;
|
||
}
|
||
if (h2 && (!h1 || h2.textContent !== h1.textContent)) {
|
||
slide.addText(h2.textContent.trim(), {
|
||
x: 0.6, y: yPos, w: '55%', h: 0.6,
|
||
fontSize: 20, color: '163374', fontFace: 'Arial',
|
||
bold: true, isTextBox: true
|
||
});
|
||
yPos += 0.7;
|
||
}
|
||
if (lis.length > 0) {
|
||
var bullets = [];
|
||
lis.forEach(function(li) {
|
||
var text = li.textContent.trim();
|
||
if (text) bullets.push({ text: text, options: { fontSize: 14, color: '333333', bullet: { code: '2013' }, indentLevel: 0 } });
|
||
});
|
||
if (bullets.length > 0) {
|
||
slide.addText(bullets, {
|
||
x: 0.6, y: yPos, w: '55%', h: 5.5 - yPos,
|
||
fontFace: 'Arial', lineSpacingMultiple: 1.3,
|
||
valign: 'top', isTextBox: true, shrinkText: true
|
||
});
|
||
}
|
||
}
|
||
if (lis.length === 0 && pars.length > 0) {
|
||
var parTexts = [];
|
||
pars.forEach(function(p) { var t = p.textContent.trim(); if (t && t.length > 2) parTexts.push(t); });
|
||
if (parTexts.length > 0) {
|
||
slide.addText(parTexts.join('\n\n'), {
|
||
x: 0.6, y: yPos, w: '55%', h: 5.5 - yPos,
|
||
fontSize: 14, color: '333333', fontFace: 'Arial',
|
||
lineSpacingMultiple: 1.4, valign: 'top', isTextBox: true, shrinkText: true
|
||
});
|
||
}
|
||
}
|
||
}
|
||
|
||
var filename = (document.title || 'praesentation').replace(/[^a-zA-Z0-9äöüÄÖÜß\-_ ]/g, '').trim();
|
||
await pptx.writeFile({ fileName: filename + '.pptx' });
|
||
btn.textContent = '⬇P';
|
||
_toast('PowerPoint heruntergeladen ✓', 3000);
|
||
};
|
||
|
||
// ── Stil-Wechsel aus stile.html automatisch erkennen und Bilder neu generieren ──
|
||
window.addEventListener('storage', function(e) {
|
||
if (e.key === _LS_KEY + '_prompt' && e.newValue && e.newValue !== e.oldValue) {
|
||
IMG_STYLE = e.newValue;
|
||
var name = localStorage.getItem(_LS_KEY + '_name') || 'Neuer Stil';
|
||
_toast('Stil gewechselt: ' + name + ' — generiere Bilder …', 3500);
|
||
setTimeout(generateAllImages, 600);
|
||
}
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|