From 82913d78b849444fe48a0ca3160ccaefaec4505b Mon Sep 17 00:00:00 2001 From: DeeCee03 Date: Wed, 26 Aug 2026 14:22:46 +0200 Subject: [PATCH] Animation: die Leiste laesst sich zuklappen Ein Klick auf den Kopf klappt sie zu, dann bleiben 40 px und der Canvas hat den Platz. Sie ist dafuer ein
mit dem Kopf als -- damit ist die ganze Zeile die Trefferflaeche und die Tastaturbedienung kommt von selbst, statt dass ein eigener Knopf eine zweite Flaeche fuer dieselbe Sache aufmacht. Ob sie offen ist, merkt sich der Browser je Projekt im localStorage und nicht der Projektstand: das ist eine Vorliebe und keine Gestaltung, in state/.json wuerde sie bei jedem einen Diff machen. In allen sechs Projekten nachgezogen. Im Streifenmodus faellt sie weiterhin ganz weg, die Uebersicht zeigt alle sieben Rahmen unveraendert, und der Bildexport laeuft wie vorher. Co-Authored-By: Claude Opus 5 (1M context) --- README.md | 6 ++++++ post2-alt.html | 45 +++++++++++++++++++++++++++++++++++++-------- post2.html | 45 +++++++++++++++++++++++++++++++++++++-------- post3.html | 45 +++++++++++++++++++++++++++++++++++++-------- post4.html | 45 +++++++++++++++++++++++++++++++++++++-------- post5.html | 45 +++++++++++++++++++++++++++++++++++++-------- post6.html | 45 +++++++++++++++++++++++++++++++++++++-------- 7 files changed, 228 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 81ada51..ca379e9 100644 --- a/README.md +++ b/README.md @@ -367,6 +367,12 @@ Unter dem Canvas liegt in **jedem** Projekt, im selben Fenster, ein Bereich „Animation". Er zeigt jede Animation als eigenes Blatt in Vorschau, mit Zeitregler, `Abspielen` und `MP4 exportieren`. +**Ein Klick auf den Kopf klappt ihn zu**, dann bleibt eine Zeile von 40 px und +der Canvas hat den Platz. Ob er offen ist, merkt sich der Browser je Projekt +(`localStorage`) und nicht der Projektstand: es ist eine Vorliebe und keine +Gestaltung, sie hat in `state/.json` nichts verloren, wo sie bei jedem +einen Diff machen würde. + **Eine Animation ist keine Slide.** Sie steht in `ANIMS` und nicht in `SLIDES`, liegt also nicht im Streifen, taucht in der Slide-Auswahl nicht auf und wird vom Bildexport nicht angefasst. Das ist der ganze Punkt: im Carousel diff --git a/post2-alt.html b/post2-alt.html index 4882e15..09920d0 100644 --- a/post2-alt.html +++ b/post2-alt.html @@ -553,16 +553,32 @@ if (location.search.indexOf("nur=anim") >= 0) und Grund, ohne dass irgendwo ein Fehler auftauchte. */ #animleiste { flex: 0 0 auto; border-top: 1px solid #24262F; - background: #14161C; padding: 13px 20px 16px; - max-height: 42vh; overflow-y: auto; + background: #14161C; padding: 0 20px; + max-height: 46vh; overflow-y: auto; } - .animkopf { display: flex; align-items: baseline; gap: 10px; margin-bottom: 11px; } + #animleiste[open] { padding-bottom: 16px; } + + /* Der Kopf ist der Schalter. Ein eigener Knopf daneben waere eine zweite + Trefferflaeche fuer dieselbe Sache -- die ganze Zeile ist gross genug, + und ein
bringt Tastaturbedienung von selbst mit. */ + .animkopf { + display: flex; align-items: center; gap: 10px; + padding: 12px 0; cursor: pointer; user-select: none; + list-style: none; + } + .animkopf::-webkit-details-marker { display: none; } + .animkopf:hover b { color: #FFFFFF; } + .animpfeil { + flex: none; width: 13px; height: 13px; color: #6E7480; + transition: transform .16s ease; + } + #animleiste[open] .animpfeil { transform: rotate(90deg); } .animkopf b { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: #E8EAEE; } - .animkopf span { font-size: 11.5px; color: #6E7480; } - .animreihe { display: flex; gap: 14px; flex-wrap: wrap; } + .animkopf > span { font-size: 11.5px; color: #6E7480; } + .animreihe { display: flex; gap: 14px; flex-wrap: wrap; padding-bottom: 2px; } .animkarte { display: flex; gap: 14px; align-items: stretch; border: 1px solid #2E313B; border-radius: 10px; @@ -3654,6 +3670,12 @@ if (location.search.indexOf("nur=anim") >= 0) /* Der Bereich unter dem Canvas. Er zeigt jede Animation als eigenes Blatt in Vorschau, nicht als Eintrag in einer Liste: was hier laeuft, ist dasselbe Blatt, das hinterher im Video steht. */ + const ANIM_OFFEN = "postgrid-anim-" + PROJECT; + const ANIM_PFEIL = + ''; + function animLeisteBauen() { const liste = window.ANIM_LISTE(); let leiste = document.getElementById("animleiste"); @@ -3669,14 +3691,21 @@ if (location.search.indexOf("nur=anim") >= 0) while (buehne.firstChild) flaeche.appendChild(buehne.firstChild); buehne.appendChild(flaeche); } - leiste = document.createElement("section"); + leiste = document.createElement("details"); leiste.id = "animleiste"; + /* Ob sie offen ist, ist eine Vorliebe und kein Projektstand: sie + gehoert in den Browser und nicht in state/.json, das + gepusht wird und wo sie bei jedem einen Diff machen wuerde. */ + leiste.open = localStorage.getItem(ANIM_OFFEN) !== "zu"; + leiste.addEventListener("toggle", () => { + localStorage.setItem(ANIM_OFFEN, leiste.open ? "auf" : "zu"); + }); (buehne || document.body).appendChild(leiste); } - const kopf = document.createElement("div"); + const kopf = document.createElement("summary"); kopf.className = "animkopf"; - kopf.innerHTML = "Animation" + + kopf.innerHTML = ANIM_PFEIL + "Animation" + (liste.length ? liste.length + (liste.length === 1 ? " Element" : " Elemente") + " · 1080 × 1350 · 30 fps · MP4, getrennt vom Bildexport" diff --git a/post2.html b/post2.html index 47b558e..d73f858 100644 --- a/post2.html +++ b/post2.html @@ -472,16 +472,32 @@ if (location.search.indexOf("nur=anim") >= 0) und Grund, ohne dass irgendwo ein Fehler auftauchte. */ #animleiste { flex: 0 0 auto; border-top: 1px solid #24262F; - background: #14161C; padding: 13px 20px 16px; - max-height: 42vh; overflow-y: auto; + background: #14161C; padding: 0 20px; + max-height: 46vh; overflow-y: auto; } - .animkopf { display: flex; align-items: baseline; gap: 10px; margin-bottom: 11px; } + #animleiste[open] { padding-bottom: 16px; } + + /* Der Kopf ist der Schalter. Ein eigener Knopf daneben waere eine zweite + Trefferflaeche fuer dieselbe Sache -- die ganze Zeile ist gross genug, + und ein
bringt Tastaturbedienung von selbst mit. */ + .animkopf { + display: flex; align-items: center; gap: 10px; + padding: 12px 0; cursor: pointer; user-select: none; + list-style: none; + } + .animkopf::-webkit-details-marker { display: none; } + .animkopf:hover b { color: #FFFFFF; } + .animpfeil { + flex: none; width: 13px; height: 13px; color: #6E7480; + transition: transform .16s ease; + } + #animleiste[open] .animpfeil { transform: rotate(90deg); } .animkopf b { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: #E8EAEE; } - .animkopf span { font-size: 11.5px; color: #6E7480; } - .animreihe { display: flex; gap: 14px; flex-wrap: wrap; } + .animkopf > span { font-size: 11.5px; color: #6E7480; } + .animreihe { display: flex; gap: 14px; flex-wrap: wrap; padding-bottom: 2px; } .animkarte { display: flex; gap: 14px; align-items: stretch; border: 1px solid #2E313B; border-radius: 10px; @@ -3284,6 +3300,12 @@ if (location.search.indexOf("nur=anim") >= 0) /* Der Bereich unter dem Canvas. Er zeigt jede Animation als eigenes Blatt in Vorschau, nicht als Eintrag in einer Liste: was hier laeuft, ist dasselbe Blatt, das hinterher im Video steht. */ + const ANIM_OFFEN = "postgrid-anim-" + PROJECT; + const ANIM_PFEIL = + ''; + function animLeisteBauen() { const liste = window.ANIM_LISTE(); let leiste = document.getElementById("animleiste"); @@ -3299,14 +3321,21 @@ if (location.search.indexOf("nur=anim") >= 0) while (buehne.firstChild) flaeche.appendChild(buehne.firstChild); buehne.appendChild(flaeche); } - leiste = document.createElement("section"); + leiste = document.createElement("details"); leiste.id = "animleiste"; + /* Ob sie offen ist, ist eine Vorliebe und kein Projektstand: sie + gehoert in den Browser und nicht in state/.json, das + gepusht wird und wo sie bei jedem einen Diff machen wuerde. */ + leiste.open = localStorage.getItem(ANIM_OFFEN) !== "zu"; + leiste.addEventListener("toggle", () => { + localStorage.setItem(ANIM_OFFEN, leiste.open ? "auf" : "zu"); + }); (buehne || document.body).appendChild(leiste); } - const kopf = document.createElement("div"); + const kopf = document.createElement("summary"); kopf.className = "animkopf"; - kopf.innerHTML = "Animation" + + kopf.innerHTML = ANIM_PFEIL + "Animation" + (liste.length ? liste.length + (liste.length === 1 ? " Element" : " Elemente") + " · 1080 × 1350 · 30 fps · MP4, getrennt vom Bildexport" diff --git a/post3.html b/post3.html index 0e40b28..276b3b7 100644 --- a/post3.html +++ b/post3.html @@ -451,16 +451,32 @@ if (location.search.indexOf("nur=anim") >= 0) und Grund, ohne dass irgendwo ein Fehler auftauchte. */ #animleiste { flex: 0 0 auto; border-top: 1px solid #24262F; - background: #14161C; padding: 13px 20px 16px; - max-height: 42vh; overflow-y: auto; + background: #14161C; padding: 0 20px; + max-height: 46vh; overflow-y: auto; } - .animkopf { display: flex; align-items: baseline; gap: 10px; margin-bottom: 11px; } + #animleiste[open] { padding-bottom: 16px; } + + /* Der Kopf ist der Schalter. Ein eigener Knopf daneben waere eine zweite + Trefferflaeche fuer dieselbe Sache -- die ganze Zeile ist gross genug, + und ein
bringt Tastaturbedienung von selbst mit. */ + .animkopf { + display: flex; align-items: center; gap: 10px; + padding: 12px 0; cursor: pointer; user-select: none; + list-style: none; + } + .animkopf::-webkit-details-marker { display: none; } + .animkopf:hover b { color: #FFFFFF; } + .animpfeil { + flex: none; width: 13px; height: 13px; color: #6E7480; + transition: transform .16s ease; + } + #animleiste[open] .animpfeil { transform: rotate(90deg); } .animkopf b { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: #E8EAEE; } - .animkopf span { font-size: 11.5px; color: #6E7480; } - .animreihe { display: flex; gap: 14px; flex-wrap: wrap; } + .animkopf > span { font-size: 11.5px; color: #6E7480; } + .animreihe { display: flex; gap: 14px; flex-wrap: wrap; padding-bottom: 2px; } .animkarte { display: flex; gap: 14px; align-items: stretch; border: 1px solid #2E313B; border-radius: 10px; @@ -2953,6 +2969,12 @@ if (location.search.indexOf("nur=anim") >= 0) /* Der Bereich unter dem Canvas. Er zeigt jede Animation als eigenes Blatt in Vorschau, nicht als Eintrag in einer Liste: was hier laeuft, ist dasselbe Blatt, das hinterher im Video steht. */ + const ANIM_OFFEN = "postgrid-anim-" + PROJECT; + const ANIM_PFEIL = + ''; + function animLeisteBauen() { const liste = window.ANIM_LISTE(); let leiste = document.getElementById("animleiste"); @@ -2968,14 +2990,21 @@ if (location.search.indexOf("nur=anim") >= 0) while (buehne.firstChild) flaeche.appendChild(buehne.firstChild); buehne.appendChild(flaeche); } - leiste = document.createElement("section"); + leiste = document.createElement("details"); leiste.id = "animleiste"; + /* Ob sie offen ist, ist eine Vorliebe und kein Projektstand: sie + gehoert in den Browser und nicht in state/.json, das + gepusht wird und wo sie bei jedem einen Diff machen wuerde. */ + leiste.open = localStorage.getItem(ANIM_OFFEN) !== "zu"; + leiste.addEventListener("toggle", () => { + localStorage.setItem(ANIM_OFFEN, leiste.open ? "auf" : "zu"); + }); (buehne || document.body).appendChild(leiste); } - const kopf = document.createElement("div"); + const kopf = document.createElement("summary"); kopf.className = "animkopf"; - kopf.innerHTML = "Animation" + + kopf.innerHTML = ANIM_PFEIL + "Animation" + (liste.length ? liste.length + (liste.length === 1 ? " Element" : " Elemente") + " · 1080 × 1350 · 30 fps · MP4, getrennt vom Bildexport" diff --git a/post4.html b/post4.html index e66d67b..f1185df 100644 --- a/post4.html +++ b/post4.html @@ -490,16 +490,32 @@ if (location.search.indexOf("nur=anim") >= 0) und Grund, ohne dass irgendwo ein Fehler auftauchte. */ #animleiste { flex: 0 0 auto; border-top: 1px solid #24262F; - background: #14161C; padding: 13px 20px 16px; - max-height: 42vh; overflow-y: auto; + background: #14161C; padding: 0 20px; + max-height: 46vh; overflow-y: auto; } - .animkopf { display: flex; align-items: baseline; gap: 10px; margin-bottom: 11px; } + #animleiste[open] { padding-bottom: 16px; } + + /* Der Kopf ist der Schalter. Ein eigener Knopf daneben waere eine zweite + Trefferflaeche fuer dieselbe Sache -- die ganze Zeile ist gross genug, + und ein
bringt Tastaturbedienung von selbst mit. */ + .animkopf { + display: flex; align-items: center; gap: 10px; + padding: 12px 0; cursor: pointer; user-select: none; + list-style: none; + } + .animkopf::-webkit-details-marker { display: none; } + .animkopf:hover b { color: #FFFFFF; } + .animpfeil { + flex: none; width: 13px; height: 13px; color: #6E7480; + transition: transform .16s ease; + } + #animleiste[open] .animpfeil { transform: rotate(90deg); } .animkopf b { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: #E8EAEE; } - .animkopf span { font-size: 11.5px; color: #6E7480; } - .animreihe { display: flex; gap: 14px; flex-wrap: wrap; } + .animkopf > span { font-size: 11.5px; color: #6E7480; } + .animreihe { display: flex; gap: 14px; flex-wrap: wrap; padding-bottom: 2px; } .animkarte { display: flex; gap: 14px; align-items: stretch; border: 1px solid #2E313B; border-radius: 10px; @@ -3788,6 +3804,12 @@ if (location.search.indexOf("nur=anim") >= 0) /* Der Bereich unter dem Canvas. Er zeigt jede Animation als eigenes Blatt in Vorschau, nicht als Eintrag in einer Liste: was hier laeuft, ist dasselbe Blatt, das hinterher im Video steht. */ + const ANIM_OFFEN = "postgrid-anim-" + PROJECT; + const ANIM_PFEIL = + ''; + function animLeisteBauen() { const liste = window.ANIM_LISTE(); let leiste = document.getElementById("animleiste"); @@ -3803,14 +3825,21 @@ if (location.search.indexOf("nur=anim") >= 0) while (buehne.firstChild) flaeche.appendChild(buehne.firstChild); buehne.appendChild(flaeche); } - leiste = document.createElement("section"); + leiste = document.createElement("details"); leiste.id = "animleiste"; + /* Ob sie offen ist, ist eine Vorliebe und kein Projektstand: sie + gehoert in den Browser und nicht in state/.json, das + gepusht wird und wo sie bei jedem einen Diff machen wuerde. */ + leiste.open = localStorage.getItem(ANIM_OFFEN) !== "zu"; + leiste.addEventListener("toggle", () => { + localStorage.setItem(ANIM_OFFEN, leiste.open ? "auf" : "zu"); + }); (buehne || document.body).appendChild(leiste); } - const kopf = document.createElement("div"); + const kopf = document.createElement("summary"); kopf.className = "animkopf"; - kopf.innerHTML = "Animation" + + kopf.innerHTML = ANIM_PFEIL + "Animation" + (liste.length ? liste.length + (liste.length === 1 ? " Element" : " Elemente") + " · 1080 × 1350 · 30 fps · MP4, getrennt vom Bildexport" diff --git a/post5.html b/post5.html index 436b1b8..a173f45 100644 --- a/post5.html +++ b/post5.html @@ -490,16 +490,32 @@ if (location.search.indexOf("nur=anim") >= 0) und Grund, ohne dass irgendwo ein Fehler auftauchte. */ #animleiste { flex: 0 0 auto; border-top: 1px solid #24262F; - background: #14161C; padding: 13px 20px 16px; - max-height: 42vh; overflow-y: auto; + background: #14161C; padding: 0 20px; + max-height: 46vh; overflow-y: auto; } - .animkopf { display: flex; align-items: baseline; gap: 10px; margin-bottom: 11px; } + #animleiste[open] { padding-bottom: 16px; } + + /* Der Kopf ist der Schalter. Ein eigener Knopf daneben waere eine zweite + Trefferflaeche fuer dieselbe Sache -- die ganze Zeile ist gross genug, + und ein
bringt Tastaturbedienung von selbst mit. */ + .animkopf { + display: flex; align-items: center; gap: 10px; + padding: 12px 0; cursor: pointer; user-select: none; + list-style: none; + } + .animkopf::-webkit-details-marker { display: none; } + .animkopf:hover b { color: #FFFFFF; } + .animpfeil { + flex: none; width: 13px; height: 13px; color: #6E7480; + transition: transform .16s ease; + } + #animleiste[open] .animpfeil { transform: rotate(90deg); } .animkopf b { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: #E8EAEE; } - .animkopf span { font-size: 11.5px; color: #6E7480; } - .animreihe { display: flex; gap: 14px; flex-wrap: wrap; } + .animkopf > span { font-size: 11.5px; color: #6E7480; } + .animreihe { display: flex; gap: 14px; flex-wrap: wrap; padding-bottom: 2px; } .animkarte { display: flex; gap: 14px; align-items: stretch; border: 1px solid #2E313B; border-radius: 10px; @@ -4030,6 +4046,12 @@ if (location.search.indexOf("nur=anim") >= 0) /* Der Bereich unter dem Canvas. Er zeigt jede Animation als eigenes Blatt in Vorschau, nicht als Eintrag in einer Liste: was hier laeuft, ist dasselbe Blatt, das hinterher im Video steht. */ + const ANIM_OFFEN = "postgrid-anim-" + PROJECT; + const ANIM_PFEIL = + ''; + function animLeisteBauen() { const liste = window.ANIM_LISTE(); let leiste = document.getElementById("animleiste"); @@ -4045,14 +4067,21 @@ if (location.search.indexOf("nur=anim") >= 0) while (buehne.firstChild) flaeche.appendChild(buehne.firstChild); buehne.appendChild(flaeche); } - leiste = document.createElement("section"); + leiste = document.createElement("details"); leiste.id = "animleiste"; + /* Ob sie offen ist, ist eine Vorliebe und kein Projektstand: sie + gehoert in den Browser und nicht in state/.json, das + gepusht wird und wo sie bei jedem einen Diff machen wuerde. */ + leiste.open = localStorage.getItem(ANIM_OFFEN) !== "zu"; + leiste.addEventListener("toggle", () => { + localStorage.setItem(ANIM_OFFEN, leiste.open ? "auf" : "zu"); + }); (buehne || document.body).appendChild(leiste); } - const kopf = document.createElement("div"); + const kopf = document.createElement("summary"); kopf.className = "animkopf"; - kopf.innerHTML = "Animation" + + kopf.innerHTML = ANIM_PFEIL + "Animation" + (liste.length ? liste.length + (liste.length === 1 ? " Element" : " Elemente") + " · 1080 × 1350 · 30 fps · MP4, getrennt vom Bildexport" diff --git a/post6.html b/post6.html index 5d53b8b..3cf3567 100644 --- a/post6.html +++ b/post6.html @@ -494,16 +494,32 @@ if (location.search.indexOf("nur=anim") >= 0) und Grund, ohne dass irgendwo ein Fehler auftauchte. */ #animleiste { flex: 0 0 auto; border-top: 1px solid #24262F; - background: #14161C; padding: 13px 20px 16px; - max-height: 42vh; overflow-y: auto; + background: #14161C; padding: 0 20px; + max-height: 46vh; overflow-y: auto; } - .animkopf { display: flex; align-items: baseline; gap: 10px; margin-bottom: 11px; } + #animleiste[open] { padding-bottom: 16px; } + + /* Der Kopf ist der Schalter. Ein eigener Knopf daneben waere eine zweite + Trefferflaeche fuer dieselbe Sache -- die ganze Zeile ist gross genug, + und ein
bringt Tastaturbedienung von selbst mit. */ + .animkopf { + display: flex; align-items: center; gap: 10px; + padding: 12px 0; cursor: pointer; user-select: none; + list-style: none; + } + .animkopf::-webkit-details-marker { display: none; } + .animkopf:hover b { color: #FFFFFF; } + .animpfeil { + flex: none; width: 13px; height: 13px; color: #6E7480; + transition: transform .16s ease; + } + #animleiste[open] .animpfeil { transform: rotate(90deg); } .animkopf b { font-size: 11px; font-weight: 700; letter-spacing: .09em; text-transform: uppercase; color: #E8EAEE; } - .animkopf span { font-size: 11.5px; color: #6E7480; } - .animreihe { display: flex; gap: 14px; flex-wrap: wrap; } + .animkopf > span { font-size: 11.5px; color: #6E7480; } + .animreihe { display: flex; gap: 14px; flex-wrap: wrap; padding-bottom: 2px; } .animkarte { display: flex; gap: 14px; align-items: stretch; border: 1px solid #2E313B; border-radius: 10px; @@ -4549,6 +4565,12 @@ if (location.search.indexOf("nur=anim") >= 0) /* Der Bereich unter dem Canvas. Er zeigt jede Animation als eigenes Blatt in Vorschau, nicht als Eintrag in einer Liste: was hier laeuft, ist dasselbe Blatt, das hinterher im Video steht. */ + const ANIM_OFFEN = "postgrid-anim-" + PROJECT; + const ANIM_PFEIL = + ''; + function animLeisteBauen() { const liste = window.ANIM_LISTE(); let leiste = document.getElementById("animleiste"); @@ -4564,14 +4586,21 @@ if (location.search.indexOf("nur=anim") >= 0) while (buehne.firstChild) flaeche.appendChild(buehne.firstChild); buehne.appendChild(flaeche); } - leiste = document.createElement("section"); + leiste = document.createElement("details"); leiste.id = "animleiste"; + /* Ob sie offen ist, ist eine Vorliebe und kein Projektstand: sie + gehoert in den Browser und nicht in state/.json, das + gepusht wird und wo sie bei jedem einen Diff machen wuerde. */ + leiste.open = localStorage.getItem(ANIM_OFFEN) !== "zu"; + leiste.addEventListener("toggle", () => { + localStorage.setItem(ANIM_OFFEN, leiste.open ? "auf" : "zu"); + }); (buehne || document.body).appendChild(leiste); } - const kopf = document.createElement("div"); + const kopf = document.createElement("summary"); kopf.className = "animkopf"; - kopf.innerHTML = "Animation" + + kopf.innerHTML = ANIM_PFEIL + "Animation" + (liste.length ? liste.length + (liste.length === 1 ? " Element" : " Elemente") + " · 1080 × 1350 · 30 fps · MP4, getrennt vom Bildexport"