{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "bildsequenz-video-scrub",
 "name": "Bildsequenz-/Video-Scrub",
 "name_en": "Scroll-scrubbed image sequence / video scrubbing",
 "kurz": "Ein Architekturmodell dreht sich Frame für Frame mit dem Scroll, das Dach hebt ab: 120 vorgeladene WebP-Bilder im gepinnten Canvas.",
 "kategorie": "Scroll & Section-Animationen",
 "kategorie_slug": "scroll",
 "kategorie_nr": 5,
 "bau_chat": "C2",
 "prioritaet": "A",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 2,
 "stimmung": [
  "präzise",
  "luxuriös",
  "filmisch"
 ],
 "stimmung_roh": [
  "technisch",
  "produkt",
  "luxuriös",
  "filmisch"
 ],
 "technik": [
  "canvas",
  "gsap",
  "scrolltrigger",
  "vanilla-js"
 ],
 "technik_gruppen": [
  "js",
  "gsap",
  "canvas"
 ],
 "leistungskosten": "hoch",
 "steckbrief": {
  "beschreibung": "Eine Section wird gepinnt, darin liegt ein Canvas in Vollbild. Eine vorgerenderte Bildfolge wird vorgeladen, typisch 60 bis 200 Frames: ein Produkt dreht sich, zerlegt sich oder die Kamera fährt. Der Scroll-Fortschritt von 0 bis 1 bestimmt den Frame-Index, der passende Frame wird ins Canvas gezeichnet. Begleitende Texte blenden an festen Fortschrittspunkten ein. Alternativ koppelt man die currentTime eines Videos an den Scroll.",
  "warum_es_wirkt": "Der Nutzer steuert einen Film mit dem Scrollrad. Das Ergebnis hat die Qualität eines Renderings, fühlt sich aber direkt an. Das Produkt wirkt greifbar, ohne dass im Browser 3D in Echtzeit läuft.",
  "wann_einsetzen": "Produktseiten für Hardware, Möbel oder Mode, Architekturvisualisierung, Launch-Seiten.",
  "wann_nicht": "Wenn die Zielgruppe oft mobil ohne WLAN unterwegs ist. Wenn kein hochwertiges Ausgangsmaterial da ist. Auf Seiten mit SEO-Fokus, wenn der Inhalt nur im Bild steckt und begleitender Text fehlt.",
  "varianten": [
   "Canvas mit Bildsequenz (WebP oder AVIF), wie auf Apple-Produktseiten",
   "Video-Scrub mit dichtem Keyframe-Encoding",
   "Start- und Endframe, dazwischen eine kurze Animation, die ab einer Schwelle abspielt",
   "Sprite-Sheet für kurze Sequenzen: eine Datei, wenige Frames"
  ],
  "umsetzung": "Frames als nummerierte AVIF- oder WebP-Dateien vorladen, je etwa 30 bis 80 kB. Die ersten 10 sofort laden, den Rest progressiv. Muster: const obj = { f: 0 }; gsap.to(obj, { f: N - 1, snap: 'f', ease: 'none', scrollTrigger: { trigger: section, pin: true, scrub: 0.5, end: '+=300%' }, onUpdate: () => draw(images[obj.f]) }). draw() zeichnet mit drawImage im object-fit-cover-Verfahren und berücksichtigt devicePixelRatio, höchstens 2. Fallstricke: Viele 4K-Frames kosten viel Speicher, mobil daher halbe Auflösung und nur jeden 2. Frame. Video-Scrub ruckelt mit normalem H.264, weil die Keyframes zu weit auseinanderliegen; mit -g 1 oder kurzer Keyframe-Distanz encodieren. Safari decodiert Sprünge in currentTime langsamer.",
  "mobil": "Weniger Frames und kleinere Auflösung, im Hochformat eine eigene Sequenz. Bei Save-Data oder langsamer Verbindung (navigator.connection) ein Standbild oder ein kurzes Loop-Video zeigen.",
  "reduzierte_bewegung": "Schlüsselframes als statische Bildfolge, mit Text untereinander.",
  "barrierefreiheit": "Canvas mit role=\"img\" und aria-label oder einer versteckten Textbeschreibung. Alle begleitenden Texte stehen im DOM, nicht im Bild."
 },
 "messwerte": {
  "easing": "none",
  "dauer_ms": "scrub 0,3–0,6 s Glättung",
  "stagger_ms": "",
  "distanz": "Pin-Strecke 200–400 % Viewport",
  "sonstiges": "60–200 Frames; DPR auf 2 begrenzen",
  "herkunft": "typisch",
  "quelle": ""
 },
 "kurve": {
  "bezier": [
   0,
   0,
   1,
   1
  ],
  "css": "cubic-bezier(0, 0, 1, 1)",
  "name": "linear",
  "dauer_ms": null
 },
 "gesehen_bei": [
  {
   "seite": "Apple AirPods Pro",
   "url": "https://www.apple.com/airpods-pro/",
   "auszeichnung": "",
   "beobachtung": "Viele Bildassets mit startframe/endframe-Benennung (Batterie, Herzfrequenz, Noise Control) und Produkt-Viewer-Sequenzen – Hinweis auf frame-basierte Scroll-Animationen; Scroll-Bindung aus Markup nicht beweisbar.",
   "art": "website"
  },
  {
   "seite": "Grand Theft Auto VI (Rockstar Games)",
   "url": "https://www.rockstargames.com/VI",
   "auszeichnung": "",
   "beobachtung": "Nutzt Lenis (lenis.dev-Showcase); Abschnitt mit ‚Scroll for more content.‘ und Bildreihe shard0–shard9 – scroll-gesteuerte Bildstrecke, Detailverhalten im Browser prüfen.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "GSAP ScrollTrigger (scrub, pin)",
   "url": "https://gsap.com/docs/v3/Plugins/ScrollTrigger/"
  }
 ],
 "kombinierbar_mit": [
  "pinned-scrub-scrollytelling",
  "scroll-fortschritt"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/scroll/bildsequenz-video-scrub/",
  "meta": "https://cecodesign.de/lab/fundus/scroll/bildsequenz-video-scrub/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/scroll/bildsequenz-video-scrub/demo"
 },
 "herkunft": {
  "quelldateien": [
   "scroll.json"
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Ein Architekturmodell dreht sich Frame für Frame mit dem Scroll, das Dach hebt ab: 120 vorgeladene WebP-Bilder im gepinnten Canvas.",
  "demo": true,
  "abhaengigkeiten": [
   "gsap@3.15.0",
   "ScrollTrigger@3.15.0"
  ],
  "werte": {
   "easing": "none (linear, Scroll = Zeitachse)",
   "scrub_s": 0.5,
   "pin": "start 'top top', end '+=300%' (Pin-Strecke 300 % Viewport)",
   "frames": "120 Desktop (1440 × 900), 60 Hochformat (600 × 1200), 24 bei Save-Data",
   "format": "WebP, Qualität 0.84",
   "frame_index": "Math.round(p × (N − 1)), p = Scroll-Fortschritt 0–1",
   "vorladen": "erst Frames 0–9, dann grob nach fein (jeder 8., 4., 2., 1.); fehlende Frames durch den nächsten geladenen ersetzt",
   "zeichnen": "drawImage im object-fit-cover-Verfahren, devicePixelRatio max. 2",
   "sprite": "24 Frames, 6 × 4 Kacheln à 480 × 300 (Hochformat 240 × 480), eine Datei",
   "start_ende": "Schwelle 50 % Fortschritt, dann Clip über alle Frames 1,2 s linear (ease none), rückwärts beim Zurückscrollen",
   "texte": "Kapitel bei 10–36 %, 36–68 %, 68–100 %, Einblendung 0,8 s cubic-bezier(0.16, 1, 0.3, 1), 18 px",
   "ui_ms": 150
  },
  "ausloeser": "scroll",
  "touch": "Gleiches Verhalten per Wischen. Hochformat lädt eine eigene, leichtere Sequenz (60 Frames, 600 × 1200), Werteliste ausgeblendet, ScrollTrigger mit ignoreMobileResize.",
  "reduziert": "Kein Pin, kein Scrub. Das erste Bild steht als Kopf, darunter drei Schlüsselbilder mit Text untereinander, die kurz einblenden (0,25 s linear).",
  "korrekturen": {
   "beschreibung": "Eine Section wird gepinnt, darin liegt ein Canvas in Vollbild. Eine vorgerenderte Bildfolge wird vorgeladen, typisch 60 bis 200 Frames: ein Produkt dreht sich, zerlegt sich oder die Kamera fährt. Der Scroll-Fortschritt von 0 bis 1 bestimmt den Frame-Index, der passende Frame wird ins Canvas gezeichnet. Begleitende Texte blenden an festen Fortschrittspunkten ein. Alternativ koppelt man die currentTime eines Videos an den Scroll.",
   "warum_es_wirkt": "Der Nutzer steuert einen Film mit dem Scrollrad. Das Ergebnis hat die Qualität eines Renderings, fühlt sich aber direkt an. Das Produkt wirkt greifbar, ohne dass im Browser 3D in Echtzeit läuft.",
   "wann_einsetzen": "Produktseiten für Hardware, Möbel oder Mode, Architekturvisualisierung, Launch-Seiten.",
   "wann_nicht": "Wenn die Zielgruppe oft mobil ohne WLAN unterwegs ist. Wenn kein hochwertiges Ausgangsmaterial da ist. Auf Seiten mit SEO-Fokus, wenn der Inhalt nur im Bild steckt und begleitender Text fehlt.",
   "varianten": [
    "Canvas mit Bildsequenz (WebP oder AVIF), wie auf Apple-Produktseiten",
    "Video-Scrub mit dichtem Keyframe-Encoding",
    "Start- und Endframe, dazwischen eine kurze Animation, die ab einer Schwelle abspielt",
    "Sprite-Sheet für kurze Sequenzen: eine Datei, wenige Frames"
   ],
   "umsetzung": "Frames als nummerierte AVIF- oder WebP-Dateien vorladen, je etwa 30 bis 80 kB. Die ersten 10 sofort laden, den Rest progressiv. Muster: const obj = { f: 0 }; gsap.to(obj, { f: N - 1, snap: 'f', ease: 'none', scrollTrigger: { trigger: section, pin: true, scrub: 0.5, end: '+=300%' }, onUpdate: () => draw(images[obj.f]) }). draw() zeichnet mit drawImage im object-fit-cover-Verfahren und berücksichtigt devicePixelRatio, höchstens 2. Fallstricke: Viele 4K-Frames kosten viel Speicher, mobil daher halbe Auflösung und nur jeden 2. Frame. Video-Scrub ruckelt mit normalem H.264, weil die Keyframes zu weit auseinanderliegen; mit -g 1 oder kurzer Keyframe-Distanz encodieren. Safari decodiert Sprünge in currentTime langsamer.",
   "mobil": "Weniger Frames und kleinere Auflösung, im Hochformat eine eigene Sequenz. Bei Save-Data oder langsamer Verbindung (navigator.connection) ein Standbild oder ein kurzes Loop-Video zeigen.",
   "reduzierte_bewegung": "Schlüsselframes als statische Bildfolge, mit Text untereinander.",
   "barrierefreiheit": "Canvas mit role=\"img\" und aria-label oder einer versteckten Textbeschreibung. Alle begleitenden Texte stehen im DOM, nicht im Bild."
  },
  "geprueft": "31.10.2026",
  "notiz": "Pavillon Seewinkel des erfundenen Atelier Nordufer als Architekturmodell: Das Modell dreht sich, das Dach hebt ab, Glaswände rücken aus, die Kamera schaut in den Innenraum. Die Frames sind ein Stellvertreter für ein echtes Rendering: Sie werden beim Laden einmal per Canvas 2D gerechnet, als WebP-Dateien kodiert und danach nur noch gezeichnet, genau wie eine geladene Sequenz. Im echten Einsatz kommen die Dateien vom Server (z. B. Blender-Export). Umschalter: Bildsequenz, Sprite-Sheet (sichtbar weicher und stufiger), Start/Ende (Clip ab 50 %). Zähler und Fortschrittsbalken zeigen den aktuellen Frame. Vorführung scrollt die Pin-Strecke selbst hin und zurück."
 }
}
