Bewegtbild: die Kurven von GSAP, der Zeiger faehrt einen Bogen
Die Website macht ihre Bewegungen mit gsap 3.14.2. Uebernommen sind die Kurven, nicht das Paket: was GSAP darueber hinaus kann -- Zeitleisten, ScrollTrigger, MotionPath -- setzt voraus, dass etwas laeuft. Hier laeuft nichts, animChat(i, t) bekommt seinen Fortschritt von aussen und ist damit selbst schon die Zeitleiste. Ein paused timeline mit .progress(t) waere dieselbe Konstruktion mit 70 KB darunter, und ein Easing ist eine Zeile. Zwei der Kurven waren ohnehin GSAPs: daempfen ist Wort fuer Wort power2.inOut, rueck ist back.out(1,70158). Die Namen stehen jetzt daneben, dazu kommen raus (power2.out) und knall (expo.out). Der Zeiger fuhr auf power2.inOut, also langsam an, in der Mitte schnell, wieder abbremsend -- die Bewegung eines Schlittens. Eine Hand ist sofort schnell und wird zum Ziel hin langsam. Und er fuhr auf der Geraden. Jetzt auf einer quadratischen Bezier, Stuetzpunkt 13 % der Strecke quer nach aussen, vom Verlauf weg. Rund 27 px Ausbuchtung auf 410 px Weg: es faellt nicht auf, das ist der Punkt. Der Klickring geht auf zwei Kurven, Radius auf expo.out und die Deckung linear hinterher. Beides auf derselben sah aus wie eine Blase, die sich aufblaest. Der Anlauf ist von 0,6 s auf 0,18 s geschrumpft. Am Ende steht das Bild eine halbe Sekunde still, damit man das Ergebnis liest; lief vorn nochmal eine halbe, waren das ueber den Schleifenstoss hinweg 1,2 von 6 Sekunden Stillstand am Stueck. MP4 neu gebaut, Werte unveraendert: H.264, 1080x1350, 30 fps, 6,0 s, stumme AAC-Spur. Geprueft ist das an Kontaktabzuegen ueber die 180 Bilder, nicht am Lauf. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U7RZ6ZpLD8Dp84Rtt4KHfv
This commit is contained in:
1 parent
7804587ca0
commit
e8f5686f30
3 files changed
+119
-14
No files matched your search
+59
-11
@@ -3537,8 +3537,12 @@ if (location.search.indexOf("nur=anim") >= 0)
|
||||
'<path d="M0,0 L0,17.5 L4.3,13.4 L7,19.4 L10.1,18 L7.4,12.2 L13,12.2 Z" ' +
|
||||
'fill="#FFFFFF" stroke="#24242B" stroke-width="1.5" stroke-linejoin="round"/></g>';
|
||||
|
||||
/* Der Ring geht auf einer anderen Kurve als er verblasst: der Radius mit
|
||||
knall, also fast sofort draussen, die Deckung linear hinterher. Beides auf
|
||||
derselben Kurve sah aus wie eine Blase, die sich aufblaest -- ein Klick
|
||||
ist ein Stoss und kein Aufpumpen. */
|
||||
const klickRing = (x, y, p) => p <= 0 || p >= 1 ? "" :
|
||||
'<circle cx="' + n1(x) + '" cy="' + n1(y) + '" r="' + n1(7 + 17 * p) +
|
||||
'<circle cx="' + n1(x) + '" cy="' + n1(y) + '" r="' + n1(7 + 17 * knall(p)) +
|
||||
'" fill="none" stroke="#24242B" stroke-width="' + n1(2.4 * (1 - p)) +
|
||||
'" opacity="' + n1(.55 * (1 - p)) + '"/>';
|
||||
|
||||
@@ -3577,20 +3581,29 @@ if (location.search.indexOf("nur=anim") >= 0)
|
||||
const innenB = B - 2 * RAND;
|
||||
const bahnO = KOPF + 8, bahnU = H - FELD - 8;
|
||||
|
||||
const zeigerAn = stufe(t, .10, .22);
|
||||
const pfeil = daempfen(stufe(t, .16, .24)); // der Pfeil an der Blase
|
||||
const klick1 = stufe(t, .22, .27);
|
||||
/* Der Zeiger faehrt bei 0,03 los und nicht mehr bei 0,10. Am Ende steht
|
||||
das Bild eine halbe Sekunde still, damit man das Ergebnis liest -- lief
|
||||
vorn nochmal eine halbe Sekunde nichts, waren das ueber den
|
||||
Schleifenstoss hinweg 1,2 von 6 Sekunden Stillstand am Stueck, und die
|
||||
Schleife sah aus, als haenge sie. Der Halt am Ende bleibt, der am
|
||||
Anfang ist auf ein Achtel geschrumpft. */
|
||||
const zeigerAn = stufe(t, .03, .19);
|
||||
const pfeil = daempfen(stufe(t, .13, .21)); // der Pfeil an der Blase
|
||||
const klick1 = stufe(t, .21, .26);
|
||||
/* rueck statt daempfen, und kuerzer: gedaempft war die Deckung nach
|
||||
fuenf Bildern fertig, waehrend die Skalierung noch eine halbe Sekunde
|
||||
von 0,96 auf 1,00 weiterkroch. Sichtbar war davon fast nichts, zu
|
||||
spueren war es als Haenger. Jetzt schnappt es in einer Drittelsekunde
|
||||
auf, schwingt einmal ganz leicht ueber und steht. */
|
||||
const auf = rueck(stufe(t, .26, .34));
|
||||
const auf = rueck(stufe(t, .25, .33));
|
||||
const wandern = daempfen(stufe(t, .40, .54));
|
||||
const klick2 = stufe(t, .56, .61);
|
||||
const zu = daempfen(stufe(t, .60, .66));
|
||||
const klappen = daempfen(stufe(t, .62, .80)); // die Aufgabe klappt auf
|
||||
const system = daempfen(stufe(t, .80, .90));
|
||||
/* raus statt daempfen: die Zeile kommt von unten herein und bleibt
|
||||
liegen. Eine Kurve, die auch langsam anfaengt, laesst sie zaeh
|
||||
aussehen -- sie soll ankommen, nicht anfahren. */
|
||||
const system = raus(stufe(t, .80, .90));
|
||||
const menueAn = Math.max(0, auf - zu);
|
||||
|
||||
let g = "";
|
||||
@@ -3674,9 +3687,25 @@ if (location.search.indexOf("nur=anim") >= 0)
|
||||
const zAn = zeigerAn * (1 - zWeg);
|
||||
if (zAn > .01) {
|
||||
const vonX = B - 60, vonY = H + 40;
|
||||
const p1 = daempfen(zeigerAn);
|
||||
let zx = vonX + (chevX - 2 - vonX) * p1;
|
||||
let zy = vonY + (chevY - 2 - vonY) * p1;
|
||||
const zuX = chevX - 2, zuY = chevY - 2;
|
||||
/* raus statt daempfen. Gedaempft faehrt der Zeiger langsam an, wird in
|
||||
der Mitte schnell und bremst wieder ab -- das ist die Bewegung eines
|
||||
Schlittens und nicht die einer Hand. Eine Hand ist sofort schnell und
|
||||
wird zum Ziel hin langsam. */
|
||||
const p1 = raus(zeigerAn);
|
||||
/* Und sie faehrt einen Bogen. Auf der Geraden zwischen Start und Ziel
|
||||
liegt kein Zeiger, den je ein Mensch gefuehrt hat; das faellt nicht
|
||||
als Fehler auf, aber die Bewegung wirkt gestellt. Der Stuetzpunkt
|
||||
sitzt quer zur Strecke, um ein Zehntel ihrer Laenge nach aussen --
|
||||
weg vom Verlauf, damit der Zeiger nicht ueber die Blasen streicht.
|
||||
Bei p1 = 1 liegt die Bahn exakt auf dem Ziel, das anschliessende
|
||||
Wandern zur Menuezeile setzt also sauber daran an. */
|
||||
const bx = zuX - vonX, by = zuY - vonY, BOGEN = .13;
|
||||
const sx = (vonX + zuX) / 2 - by * BOGEN;
|
||||
const sy = (vonY + zuY) / 2 + bx * BOGEN;
|
||||
const u = 1 - p1;
|
||||
let zx = u * u * vonX + 2 * u * p1 * sx + p1 * p1 * zuX;
|
||||
let zy = u * u * vonY + 2 * u * p1 * sy + p1 * p1 * zuY;
|
||||
if (wandern > 0) {
|
||||
zx += (m.zielX - zx) * wandern;
|
||||
zy += (m.zielY - 4 - zy) * wandern;
|
||||
@@ -3707,10 +3736,29 @@ if (location.search.indexOf("nur=anim") >= 0)
|
||||
/* Ein paar Verlaeufe. Linear sieht nach Maschine aus, deshalb sind Ein-
|
||||
und Ausgang gedaempft. `stufe` blendet einen Abschnitt zwischen zwei
|
||||
Zeitpunkten ein und liefert 0 davor und 1 danach. */
|
||||
const daempfen = x => x <= 0 ? 0 : x >= 1 ? 1 : x < .5
|
||||
/* Die Kurven sind die von GSAP, mit dem die Website ihre Bewegungen macht --
|
||||
als Formel und nicht als Bibliothek. Ein Verlauf ist eine Zeile Rechnung;
|
||||
was GSAP darueber hinaus koennte (Zeitleisten, Motion-Path, ScrollTrigger),
|
||||
braucht hier nichts: die Zeichenfunktion bekommt ihr t von aussen und ist
|
||||
damit selbst schon die Zeitleiste. Die Namen stehen daneben, damit
|
||||
nachvollziehbar bleibt, welche Kurve gemeint ist.
|
||||
|
||||
daempfen und rueck standen vorher unbenannt hier und sind Wort fuer Wort
|
||||
GSAPs power2.inOut und back.out(1,70158) -- die Datei sprach die Sprache
|
||||
also schon, sie sagte es nur nicht. */
|
||||
const daempfen = x => x <= 0 ? 0 : x >= 1 ? 1 : x < .5 // power2.inOut
|
||||
? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2;
|
||||
const rueck = x => x <= 0 ? 0 : x >= 1 ? 1
|
||||
const rueck = x => x <= 0 ? 0 : x >= 1 ? 1 // back.out(1.7)
|
||||
: 1 + 2.7 * Math.pow(x - 1, 3) + 1.7 * Math.pow(x - 1, 2);
|
||||
/* Schnell los, lang aus. Alles, was ankommt und liegen bleibt -- ein Zeiger,
|
||||
der ins Bild faehrt, eine Zeile, die einlaeuft -- gehoert hierher und
|
||||
nicht auf eine Kurve, die auch langsam anfaengt. */
|
||||
const raus = x => x <= 0 ? 0 : x >= 1 ? 1 // power2.out
|
||||
: 1 - Math.pow(1 - x, 3);
|
||||
/* Noch schaerfer: schnappt heraus und ist praktisch sofort fertig. Fuer den
|
||||
Klickring, der einem Fingertipp folgt. */
|
||||
const knall = x => x <= 0 ? 0 : x >= 1 ? 1 // expo.out
|
||||
: 1 - Math.pow(2, -10 * x);
|
||||
const stufe = (t, von, bis) => t <= von ? 0 : t >= bis ? 1 : (t - von) / (bis - von);
|
||||
|
||||
const VIS = {
|
||||
|
||||
Reference in new issue
Block a user