From 7fb1c3dfcbb9adcfd0f290788342e827df497f11 Mon Sep 17 00:00:00 2001 From: DeeCee03 Date: Thu, 27 Aug 2026 16:21:46 +0200 Subject: [PATCH] Vorschau: der Abspielen-Knopf tat beim ersten Klick nichts animAbspielen rechnete performance.now() - ANIM_T[i] * dauer, damit die Vorschau dort weiterlaeuft, wo der Regler steht. ANIM_T[i] ist aber undefined, solange der Regler nie bewegt wurde: daraus wird NaN, der Fortschritt wird NaN, und animT() liefert wegen seines eigenen "|| 0" brav wieder 0. Die Vorschau stand still, ohne dass in der Konsole etwas auftauchte. Bemerkt wurde es nicht, weil jede Pruefung vorher animSetzen() aufgerufen hatte, um irgendetwas zu messen -- und damit genau den Zustand herstellte, in dem es funktioniert. Ein Pruefskript, das den Anfangszustand anfasst, prueft ihn nicht mehr. animSetzen weist NaN jetzt zusaetzlich mit Number.isFinite ab, damit so ein Wert gar nicht erst in den Stand kommt. In allen sechs Projekten nachgezogen. Der Export war davon nicht betroffen; der Weg ueber POST /anim ist noch einmal vom Knopf bis zur fertigen Datei durchgefahren worden. Co-Authored-By: Claude Opus 5 (1M context) --- POST-6.md | 17 ++++++++++++++++- animation/post6-animChat.mp4 | Bin 1135600 -> 1135629 bytes post2-alt.html | 10 ++++++++-- post2.html | 10 ++++++++-- post3.html | 10 ++++++++-- post4.html | 10 ++++++++-- post5.html | 10 ++++++++-- post6.html | 10 ++++++++-- state/post6.json | 6 +++++- 9 files changed, 69 insertions(+), 14 deletions(-) diff --git a/POST-6.md b/POST-6.md index 6aed016..1d57c75 100644 --- a/POST-6.md +++ b/POST-6.md @@ -316,7 +316,7 @@ violett.** Im Original steht dort `bg-surface-neutral-primary` mit Rand und --- -## 6. Sechzehn Fallen aus diesem Bau +## 6. Siebzehn Fallen aus diesem Bau **Die Listenzeile hat drei Zeilen, nicht zwei.** Der erste Anlauf setzte Titel und Vorschau untereinander und schob Nadel und Ungelesen-Punkt rechts neben @@ -444,6 +444,21 @@ nicht, was das Produkt heute kann. Wo eine Aussage der Website (hier: im vorliegenden Code hat, ist das ein Grund nachzufragen und nicht, die Aussage auf den vorhandenen Code zu biegen. +**Ein `|| 0` an der falschen Stelle verdeckt ein NaN.** Der Abspielen-Knopf tat +nichts, sobald man ihn nach dem Laden als Erstes anfasste. `animAbspielen` +rechnete `performance.now() - ANIM_T[i] * dauer`, damit die Vorschau dort +weiterläuft, wo der Regler steht — nur ist `ANIM_T[i]` undefined, solange der +Regler nie bewegt wurde. Daraus wird NaN, der Fortschritt wird NaN, und +`animT()` liefert wegen seines eigenen `|| 0` brav wieder 0: die Vorschau stand +still, ohne dass in der Konsole etwas auftauchte. + +Der Fehler war vier Commits alt und wurde nicht bemerkt, weil jede Prüfung +vorher `animSetzen()` aufgerufen hatte, um irgendetwas zu messen — und damit +genau den Zustand herstellte, in dem es funktioniert. **Ein Prüfskript, das den +Anfangszustand anfasst, prüft ihn nicht mehr.** `animSetzen` weist NaN jetzt +zusätzlich mit `Number.isFinite` ab, damit ein solcher Wert gar nicht erst in +den Stand kommt. + --- ## 7. Das Bewegtbild diff --git a/animation/post6-animChat.mp4 b/animation/post6-animChat.mp4 index c0b04636eba31680cc674a0644bb1c7cf8dc0a03..f755969714917c2e80e96930628cb93b618c3dc3 100644 GIT binary patch delta 3323 zcmY+^c{EjPAHeb7Iredm&E^~wGF&oMDrqnzMRap1kyI#YPE=-PI_Q?+Qi>d@kh(ch z#zLmhHIylrNTvoSaVe3jDBfRht9Pw;t^IxW-p|_q?C1HcXEc3741Yt;5jrg|--T`| z%y9ysy8;l*A9q@RTs2FN@ecqiFODXX!U(|mMfrbHP)}l>7p6CJ6 zdm)e~>wyfY12XtGAVW?8c{&ms0`klW;F4$ZfDBIqGExk)1u`lV$mmia&y@oi>ks6` z6+m9H0y1GEki2vt6D@#DwFEM)7|0s|K;Dc1vPKxlr+PrPZUC}F1;l1^fnq)ZN+cgB zvJoh8d{%w{l*S35%;o{*7!H(cFHjzJT%dwzK*jwFRMHNhQWJs75&|mE8mK~Hpvsp4 zRW%2wM+bqbzYkP{CiWbtMtpB<0IEqFsE^|y&R7oON_D`tNCWnv^}s$$0y{+j><3Q3 z?oI*rhkt=1Apnm0b>OU+29DWB;A{>Cj+M!79D0DWMHAy47vkkL70 z)P;;PkjQOpj@ z!9F7+Lu7;>e2GFv1IUO37EB_eN62UeGO9pE0mx`KGTMTSc*w{R8O=dPF~}$g85tv^ z4rHW=jH;0l$_O?^MqWrL2EBO^m( zbR8L)A)|H3=pHgUfsDd{te!$fI>-p;JLVvxOk`A!jP4?%N@VmGGQwvK7i1)ji~^7m zYVasUMuF4FXb2hEAft;w-JL{67C;qDA)`geNCX+}K}Oj~NFMte3E5*c$Ve3#jUXcp zWK@NWt|B8{WJDmNPGqzb8O0%^QDoGIj4mOg31oz%HlIX68*FgsKt3v%7uJn@G%#PR z82Kn+N3bI7D-v?RGO$lbXf1XX8;%=QOrr&#j#CPcQ=(yXOsFtUiMSjGeTp-@m^%+M=T^@8UYl zxpf1coN8Op@CN40b^cZCecA3XG2KMdRVl};e7A~=$2YU@2!9sJ&`Ym&Vo9C3%XDsg zx!-zX`b%}(#Lz}=;I=x>v%U2EfK1O{!dwNSkNlOz9^Ss??3~{h{Ps#h!iGSzMI^y`lfVShSb4>LxTUFkx zcR9Dcs5@`=X~xvMwFf!EpB1h(s-8)A9vp4v*E&vjTz+g?R@}!hYP6_*`N%5W?#eSi z50+ZH|LvuwX3Op_H7C0#`jU^PcIGlEUWp1#@&2YNK^iOYsLlDq<85}jMzeV}^%XAD zEo};_AC6kBl@B|w5S^y!SVt~ppWy0Lt|=YPF6>bcvVXVKft`b{gQOrmQ#N>qka)#)w=TPEmPa=SVrK7}MG>WmtPj#P}_*u1&( zq4a=S-{K|W;Rh@rXuZxVn`!%MW3|Zrae9$<>BiUG{cLu$@1}=&r*o?;DkeieFSZ&i zJEYpyZz)(W8k4nmUzU9UfBxF+BW8j6jknva)+Fyq&N}`f>@*d&`m)MfW0!yj`k``m z4&JNIFPYc3qbd6o>$@9MN}hTW!*8&D8{%(Lc!*CNUrh{{Tq)woHQ~t>a)BTUzq}?2 zv}Hd3@2mj&x}U^YS%poKjA)h$(BJF6RQShOj*7mf7+N$`!0Sthsmxmb^?tt5L95ASb+PB~9~-gvocpJab7K0Ahmp4a zU*BehXDS95UR`zby0p&J%*>qykCWD9m9>15pU1z|rZ>Di_0pkflf*K0P5!rygS%&c z=e8O-{hFJ%^jU{`bwRhZSNaw;r+<9SYZQ*DI{aZu{v$0#{GMX6@pQU7QFoVJQfHrwwzz|!$*@o?!j(zGt$_x#5m(y!cKu3L3sW%+I^*i9Po2e>x08MWL^PsaN_ z$V7n*cjZ9Np=bSh%k0BNr<#LVA+0w*ebVx6_%(Kp`2=IHs{iOQK~Us{6)YL!hG&O8 zJm!0wBuSc|V8l4g@sl7Vz?X7>)rf*tTGPobIId@zC7#kcNHVk@jQD^a~ zg4%{a2kwBnR-kc_>5RuOD%W{rRB!5a3tt^omCd$0ectYsr}OXlakNTWSy>7lYJM9SaYpU$rD zDkjgBeG}JST{75BnA=M!co$T5x$i96lf)kol$S3omHw#I@X=4iU`XEK_i4G1|E}nq kQ_EYfh*;;FX@-EKarpKS5);M5FbWgLBnr2Ou#;N<0}K%krvLx| delta 3272 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 diff --git a/post2-alt.html b/post2-alt.html index 09920d0..4e2b451 100644 --- a/post2-alt.html +++ b/post2-alt.html @@ -3600,7 +3600,8 @@ if (location.search.indexOf("nur=anim") >= 0) ({ i, key: a.key, dauer: a.dauer || 0, titel: a.eyebrow || a.key })); window.animSetzen = (i, t) => { - ANIM_T[i] = Math.max(0, Math.min(1, t)); + // Number.isFinite faengt NaN ab, bevor es im Stand landet. + ANIM_T[i] = Number.isFinite(t) ? Math.max(0, Math.min(1, t)) : 0; animZeichnen(i); const s = document.querySelector('input[data-animschieber="' + i + '"]'); if (s && document.activeElement !== s) s.value = String(Math.round(ANIM_T[i] * 1000)); @@ -3620,7 +3621,12 @@ if (location.search.indexOf("nur=anim") >= 0) if (alt === knopf) return; } const dauer = (ANIMS[i].dauer || 4) * 1000; - const start = performance.now() - ANIM_T[i] * dauer; + /* Weiter, wo der Regler steht -- und bei 0 anfangen, wenn er noch nie + bewegt wurde. Ohne das || 0 ist ANIM_T[i] beim ersten Klick undefined, + start wird NaN, der Fortschritt wird NaN, und animT() liefert wegen + `|| 0` brav wieder 0: die Vorschau stand still, ohne dass irgendwo ein + Fehler auftauchte. */ + const start = performance.now() - (ANIM_T[i] || 0) * dauer; knopf.textContent = "Anhalten"; const schritt = jetzt => { window.animSetzen(i, ((jetzt - start) % dauer) / dauer); diff --git a/post2.html b/post2.html index d73f858..7f58e04 100644 --- a/post2.html +++ b/post2.html @@ -3230,7 +3230,8 @@ if (location.search.indexOf("nur=anim") >= 0) ({ i, key: a.key, dauer: a.dauer || 0, titel: a.eyebrow || a.key })); window.animSetzen = (i, t) => { - ANIM_T[i] = Math.max(0, Math.min(1, t)); + // Number.isFinite faengt NaN ab, bevor es im Stand landet. + ANIM_T[i] = Number.isFinite(t) ? Math.max(0, Math.min(1, t)) : 0; animZeichnen(i); const s = document.querySelector('input[data-animschieber="' + i + '"]'); if (s && document.activeElement !== s) s.value = String(Math.round(ANIM_T[i] * 1000)); @@ -3250,7 +3251,12 @@ if (location.search.indexOf("nur=anim") >= 0) if (alt === knopf) return; } const dauer = (ANIMS[i].dauer || 4) * 1000; - const start = performance.now() - ANIM_T[i] * dauer; + /* Weiter, wo der Regler steht -- und bei 0 anfangen, wenn er noch nie + bewegt wurde. Ohne das || 0 ist ANIM_T[i] beim ersten Klick undefined, + start wird NaN, der Fortschritt wird NaN, und animT() liefert wegen + `|| 0` brav wieder 0: die Vorschau stand still, ohne dass irgendwo ein + Fehler auftauchte. */ + const start = performance.now() - (ANIM_T[i] || 0) * dauer; knopf.textContent = "Anhalten"; const schritt = jetzt => { window.animSetzen(i, ((jetzt - start) % dauer) / dauer); diff --git a/post3.html b/post3.html index 276b3b7..b49c5ee 100644 --- a/post3.html +++ b/post3.html @@ -2899,7 +2899,8 @@ if (location.search.indexOf("nur=anim") >= 0) ({ i, key: a.key, dauer: a.dauer || 0, titel: a.eyebrow || a.key })); window.animSetzen = (i, t) => { - ANIM_T[i] = Math.max(0, Math.min(1, t)); + // Number.isFinite faengt NaN ab, bevor es im Stand landet. + ANIM_T[i] = Number.isFinite(t) ? Math.max(0, Math.min(1, t)) : 0; animZeichnen(i); const s = document.querySelector('input[data-animschieber="' + i + '"]'); if (s && document.activeElement !== s) s.value = String(Math.round(ANIM_T[i] * 1000)); @@ -2919,7 +2920,12 @@ if (location.search.indexOf("nur=anim") >= 0) if (alt === knopf) return; } const dauer = (ANIMS[i].dauer || 4) * 1000; - const start = performance.now() - ANIM_T[i] * dauer; + /* Weiter, wo der Regler steht -- und bei 0 anfangen, wenn er noch nie + bewegt wurde. Ohne das || 0 ist ANIM_T[i] beim ersten Klick undefined, + start wird NaN, der Fortschritt wird NaN, und animT() liefert wegen + `|| 0` brav wieder 0: die Vorschau stand still, ohne dass irgendwo ein + Fehler auftauchte. */ + const start = performance.now() - (ANIM_T[i] || 0) * dauer; knopf.textContent = "Anhalten"; const schritt = jetzt => { window.animSetzen(i, ((jetzt - start) % dauer) / dauer); diff --git a/post4.html b/post4.html index f1185df..1480d48 100644 --- a/post4.html +++ b/post4.html @@ -3734,7 +3734,8 @@ if (location.search.indexOf("nur=anim") >= 0) ({ i, key: a.key, dauer: a.dauer || 0, titel: a.eyebrow || a.key })); window.animSetzen = (i, t) => { - ANIM_T[i] = Math.max(0, Math.min(1, t)); + // Number.isFinite faengt NaN ab, bevor es im Stand landet. + ANIM_T[i] = Number.isFinite(t) ? Math.max(0, Math.min(1, t)) : 0; animZeichnen(i); const s = document.querySelector('input[data-animschieber="' + i + '"]'); if (s && document.activeElement !== s) s.value = String(Math.round(ANIM_T[i] * 1000)); @@ -3754,7 +3755,12 @@ if (location.search.indexOf("nur=anim") >= 0) if (alt === knopf) return; } const dauer = (ANIMS[i].dauer || 4) * 1000; - const start = performance.now() - ANIM_T[i] * dauer; + /* Weiter, wo der Regler steht -- und bei 0 anfangen, wenn er noch nie + bewegt wurde. Ohne das || 0 ist ANIM_T[i] beim ersten Klick undefined, + start wird NaN, der Fortschritt wird NaN, und animT() liefert wegen + `|| 0` brav wieder 0: die Vorschau stand still, ohne dass irgendwo ein + Fehler auftauchte. */ + const start = performance.now() - (ANIM_T[i] || 0) * dauer; knopf.textContent = "Anhalten"; const schritt = jetzt => { window.animSetzen(i, ((jetzt - start) % dauer) / dauer); diff --git a/post5.html b/post5.html index a173f45..a30345d 100644 --- a/post5.html +++ b/post5.html @@ -3976,7 +3976,8 @@ if (location.search.indexOf("nur=anim") >= 0) ({ i, key: a.key, dauer: a.dauer || 0, titel: a.eyebrow || a.key })); window.animSetzen = (i, t) => { - ANIM_T[i] = Math.max(0, Math.min(1, t)); + // Number.isFinite faengt NaN ab, bevor es im Stand landet. + ANIM_T[i] = Number.isFinite(t) ? Math.max(0, Math.min(1, t)) : 0; animZeichnen(i); const s = document.querySelector('input[data-animschieber="' + i + '"]'); if (s && document.activeElement !== s) s.value = String(Math.round(ANIM_T[i] * 1000)); @@ -3996,7 +3997,12 @@ if (location.search.indexOf("nur=anim") >= 0) if (alt === knopf) return; } const dauer = (ANIMS[i].dauer || 4) * 1000; - const start = performance.now() - ANIM_T[i] * dauer; + /* Weiter, wo der Regler steht -- und bei 0 anfangen, wenn er noch nie + bewegt wurde. Ohne das || 0 ist ANIM_T[i] beim ersten Klick undefined, + start wird NaN, der Fortschritt wird NaN, und animT() liefert wegen + `|| 0` brav wieder 0: die Vorschau stand still, ohne dass irgendwo ein + Fehler auftauchte. */ + const start = performance.now() - (ANIM_T[i] || 0) * dauer; knopf.textContent = "Anhalten"; const schritt = jetzt => { window.animSetzen(i, ((jetzt - start) % dauer) / dauer); diff --git a/post6.html b/post6.html index b16c8bb..624b49f 100644 --- a/post6.html +++ b/post6.html @@ -4463,7 +4463,8 @@ if (location.search.indexOf("nur=anim") >= 0) ({ i, key: a.key, dauer: a.dauer || 0, titel: a.eyebrow || a.key })); window.animSetzen = (i, t) => { - ANIM_T[i] = Math.max(0, Math.min(1, t)); + // Number.isFinite faengt NaN ab, bevor es im Stand landet. + ANIM_T[i] = Number.isFinite(t) ? Math.max(0, Math.min(1, t)) : 0; animZeichnen(i); const s = document.querySelector('input[data-animschieber="' + i + '"]'); if (s && document.activeElement !== s) s.value = String(Math.round(ANIM_T[i] * 1000)); @@ -4483,7 +4484,12 @@ if (location.search.indexOf("nur=anim") >= 0) if (alt === knopf) return; } const dauer = (ANIMS[i].dauer || 4) * 1000; - const start = performance.now() - ANIM_T[i] * dauer; + /* Weiter, wo der Regler steht -- und bei 0 anfangen, wenn er noch nie + bewegt wurde. Ohne das || 0 ist ANIM_T[i] beim ersten Klick undefined, + start wird NaN, der Fortschritt wird NaN, und animT() liefert wegen + `|| 0` brav wieder 0: die Vorschau stand still, ohne dass irgendwo ein + Fehler auftauchte. */ + const start = performance.now() - (ANIM_T[i] || 0) * dauer; knopf.textContent = "Anhalten"; const schritt = jetzt => { window.animSetzen(i, ((jetzt - start) % dauer) / dauer); diff --git a/state/post6.json b/state/post6.json index d6a648e..bb4cbf6 100644 --- a/state/post6.json +++ b/state/post6.json @@ -22,7 +22,7 @@ "int": "dezent" } ], - "current": 0, + "current": 1, "deck": [ { "ref": "chat", @@ -54,6 +54,10 @@ { "headline": { "dy": 3 + }, + "vis": { + "dx": 4, + "dy": -88 } }, {