{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "drag-slider-traegheit-loop",
 "name": "Drag-Slider mit Trägheit und Endlosschleife",
 "name_en": "Draggable infinite slider with inertia / momentum carousel",
 "kurz": "Eine endlose Projektreihe, die dem Zeiger 1:1 folgt, mit Schwung ausgleitet und auf dem nächsten Slide einrastet.",
 "kategorie": "Galerien & Slider",
 "kategorie_slug": "galerien-slider",
 "kategorie_nr": 12,
 "bau_chat": "C6",
 "prioritaet": "A",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 3,
 "stimmung": [
  "editorial",
  "verspielt"
 ],
 "stimmung_roh": [
  "taktil",
  "verspielt",
  "modern",
  "editorial"
 ],
 "technik": [
  "gsap",
  "draggable",
  "inertia",
  "observer",
  "vanilla-js",
  "css"
 ],
 "technik_gruppen": [
  "css",
  "js",
  "gsap"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Eine Reihe von Slides läuft ohne Anfang und Ende. Eine einzige Zahl (die x-Position eines unsichtbaren Proxys) bestimmt alles: Jeder Slide sitzt bei i mal Slidebreite plus Position, per Modulo in die Gesamtbreite gefaltet. Wer zieht, bewegt den Proxy mit Draggable 1:1. Beim Loslassen übernimmt InertiaPlugin den Schwung, und eine Snap-Funktion rundet die natürliche Landeposition auf den nächsten Slide. Pfeile und Tasten springen per Tween zum Nachbarn. Zähler und Bildunterschrift folgen dem aktiven Slide.",
  "warum_es_wirkt": "Die Reihe fühlt sich an wie ein Gegenstand: Sie folgt dem Finger ohne Verzug und gleitet glaubwürdig aus. Das Einrasten schafft danach wieder Ordnung. Weil es kein Ende gibt, entsteht kein Gefühl von Begrenzung.",
  "wann_einsetzen": "Für Projektreihen, Produktkollektionen, Teamfotos, Referenzlogos und Stimmen von Kunden. Überall dort, wo man stöbern soll und nicht der Reihe nach lesen muss.",
  "wann_nicht": "Bei weniger als vier Elementen. Wenn die Reihenfolge verbindlich ist, etwa bei Schritten oder Preisen. Wenn Karten Formularelemente enthalten, denn dann konkurrieren Ziehen und Klicken.",
  "varianten": [
   "Einrasten: aktiver Slide in der Mitte, Nachbarn gedimmt, Wurf endet immer auf einem Slide",
   "Tempo: die Reihe neigt sich beim schnellen Ziehen (skewX nach Geschwindigkeit), das Bild im Slide läuft 10 bis 20 Prozent des Wegs gegen",
   "Laufband: läuft von selbst weiter, lässt sich greifen und werfen und kehrt danach in seine Bewegung zurück, in Richtung des letzten Wurfs",
   "Scroll-gekoppelt: Mausrad oder Trackpad treiben dieselbe Position (GSAP Observer)"
  ],
  "umsetzung": "Draggable auf ein Proxy-Element, nicht auf die Slides. Die Proxy-x-Position ist die Wahrheit; die Slides werden pro Frame daraus gesetzt (Modulo-Wrap) oder über den GSAP-Helfer horizontalLoop als Zeitleiste geführt. Snap rechnet in Slidebreiten, so wählt der Wurf automatisch den kürzesten Weg über den Loop-Rand. Fallstricke: bei Resize Breiten neu messen und die Position im Verhältnis umrechnen. Bewegung unter etwa 10 px als Klick werten und den letzten Snap behalten. Bilder mit draggable=false und user-select: none. Vor jedem eigenen Tween den Proxy auf die aktuelle Position setzen, sonst springt er. Jeder Pfeil-Button braucht ein eigenes aria-label.",
  "mobil": "Draggable funktioniert mit Touch. Vertikales Scrollen der Seite darf nicht blockiert werden: allowNativeTouchScrolling bzw. lockAxis. Alternative auf Mobilgeräten: natives overflow-x mit scroll-snap.",
  "reduzierte_bewegung": "Kein Autoplay, kein Schwung, keine Neigung. Beim Loslassen sofort einrasten. Navigation als Sprung oder mit kurzer Blende von 200 ms.",
  "barrierefreiheit": "Container mit role=region und aria-roledescription=carousel, jeder Slide als Gruppe mit aria-label \"n von m\". Pfeiltasten und sichtbare Buttons mit eigenen Labels. Slides außerhalb des Bildes mit aria-hidden oder inert. Läuft die Reihe von selbst, braucht sie einen Pause-Button (WCAG 2.2.2)."
 },
 "messwerte": {
  "easing": "Loop: none; Navigation: power3.out (≈ cubic-bezier(0.25,1,0.5,1)); UI-Übergänge: cubic-bezier(0.625,0.05,0,1)",
  "dauer_ms": "Navigation 725; Zähler 450; Bildunterschrift 525; Slide-Opazität 400",
  "stagger_ms": "Bildunterschrift-Verzögerung 300",
  "distanz": "Drag-Toleranz 10 px; Loop-Geschwindigkeit 100 px/s bei speed 1",
  "sonstiges": "Produktion Trionn: dragResistance 0.12, throwResistance 2500, Wrap per Modulo; Terminal: Snap-Reaktivierung 50 ms nach Wurfende. Demo Osmo: overshootTolerance 0, Wiedergabe pausiert beim Drücken.",
  "herkunft": "beobachtet",
  "quelle": "https://trionn.com/_next/static/chunks/0eox~aw2ff066.js"
 },
 "kurve": {
  "bezier": [
   0.25,
   1,
   0.5,
   1
  ],
  "css": "cubic-bezier(0.25, 1, 0.5, 1)",
  "name": "power3.out",
  "dauer_ms": 725
 },
 "gesehen_bei": [
  {
   "seite": "Osmo – Draggable Infinite Slider (GSAP Draggable), Original von Ilja van Eck",
   "url": "https://www.osmo.supply/resource/draggable-infinite-slider-with-gsap",
   "auszeichnung": "",
   "beobachtung": "horizontalLoop plus Draggable (type x, inertia true, overshootTolerance 0); Snap rechnet die Drag-Position in Zeitleistenzeit um und wählt den kürzesten Weg; Klick-Navigation 0,725 s power3; Zähler-Animation 0,45 s power3; bei Drag unter 10 px wird der letzte Snap-Wert wiederverwendet.",
   "art": "demo"
  },
  {
   "seite": "Osmo – Draggable Marquee (Directional)",
   "url": "https://www.osmo.supply/resource/draggable-marquee-directional",
   "auszeichnung": "",
   "beobachtung": "Laut Ressourcenliste ein ziehbares, richtungsabhängiges Laufband (Seite selbst nicht im Detail gelesen).",
   "art": "demo"
  },
  {
   "seite": "Codrops – Mastering Carousels with GSAP (04/2025)",
   "url": "https://tympanus.net/codrops/2025/04/21/mastering-carousels-with-gsap-from-basics-to-advanced-animation/",
   "auszeichnung": "",
   "beobachtung": "Laut Teaser: Karussells mit GSAP inklusive Scroll-Snapping, 3D-Effekten und Draggable (Artikeltext konnte nicht abgerufen werden).",
   "art": "artikel"
  },
  {
   "seite": "Trionn",
   "url": "https://trionn.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): Endlos-Laufband: Kopien angehängt, Position per Modulo zurückgesetzt, Auto-Lauf mit Lerp; GSAP Draggable type x, inertia true, dragResistance .12, throwResistance 2500; Pause bei Hover/Drag.",
   "art": "website",
   "browser_gemessen": true
  },
  {
   "seite": "Terminal Industries",
   "url": "https://terminal-industries.com/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): Drag-Karussell mit Trägheit: set(-x, { inertia: true, snapPoints, min/max }), scroll-snap währenddessen deaktiviert und nach 50 ms wieder aktiv.",
   "art": "website",
   "browser_gemessen": true
  },
  {
   "seite": "Fiddle.Digital",
   "url": "https://fiddle.digital/",
   "auszeichnung": "",
   "beobachtung": "Live geprüft 31.10.2026 (HTML/Bundle per curl abgerufen): Laufband-Komponente mit Optionen marquee-draggable, marquee-drag-friction und marquee-drag-sensitivity.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "GSAP Helper: seamlessLoop / horizontalLoop",
   "url": "https://gsap.com/docs/v3/HelperFunctions/helpers/seamlessLoop"
  },
  {
   "titel": "GSAP InertiaPlugin",
   "url": "https://gsap.com/docs/v3/Plugins/InertiaPlugin/"
  },
  {
   "titel": "Codrops: Mastering Carousels with GSAP",
   "url": "https://tympanus.net/codrops/2025/04/21/mastering-carousels-with-gsap-from-basics-to-advanced-animation/"
  },
  {
   "titel": "Codrops: Crafting a Scrollable and Draggable Parallax Slider",
   "url": "https://tympanus.net/codrops/2020/12/01/crafting-a-scrollable-and-draggable-parallax-slider/"
  }
 ],
 "kombinierbar_mit": [
  "slideshow-innere-gegenparallaxe",
  "galerie-shared-element-vollbild",
  "token-studio-signatur",
  "token-physik-traege"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/galerien-slider/drag-slider-traegheit-loop/",
  "meta": "https://cecodesign.de/lab/fundus/galerien-slider/drag-slider-traegheit-loop/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/galerien-slider/drag-slider-traegheit-loop/demo"
 },
 "herkunft": {
  "quelldateien": [
   "galerien_stile.json",
   "patch-belege-2.json"
  ],
  "pruefnotizen": [
   "patch-belege-2.json: 3 Produktionsbelege."
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Eine endlose Projektreihe, die dem Zeiger 1:1 folgt, mit Schwung ausgleitet und auf dem nächsten Slide einrastet.",
  "demo": true,
  "abhaengigkeiten": [
   "gsap@3.15.0",
   "Draggable@3.15.0",
   "InertiaPlugin@3.15.0"
  ],
  "werte": {
   "schleife": "eigene Wrap-Funktion: x = Mitte + wrap(i · Schritt + pos), Bereich ±Gesamtbreite/2; keine Klone bei 8 Slides",
   "proxy": "Draggable type x auf unsichtbarem Proxy, trigger = Bahn, allowNativeTouchScrolling true",
   "einrasten": "inertia true, throwResistance 1000, overshootTolerance 0, dragResistance 0, snap = Math.round(x / Schritt) · Schritt",
   "klick_toleranz_px": 10,
   "klick_regel": "Bewegung unter 10 px: letzter Snap-Wert bleibt; Klick auf Nachbarkarte springt dorthin",
   "navigation": "725 ms power3.out (cubic-bezier(0.25, 1, 0.5, 1)), Pfeil-Buttons und Pfeiltasten",
   "zaehler": "450 ms power3.out, Ziffer rollt in Maske (yPercent ±100)",
   "bildunterschrift": "525 ms cubic-bezier(0.625, 0.05, 0, 1), Verzögerung 300 ms, +40 ms je Zeile, translateY 105 % → 0",
   "slide_opazitaet": "inaktiv 0.42 → aktiv 1, 400 ms cubic-bezier(0.625, 0.05, 0, 1)",
   "tempo_neigung": "skewX = −v · 0.003° (v in px/s), max ±6°, lerp 0.12 je Frame",
   "tempo_parallaxe": "Bild scale 1.24, läuft 10 % des Wegs gegen, max ±12 % der Kartenbreite",
   "laufband": "100 px/s, Anlauf und Halt lerp 0.05 je Frame, dragResistance 0.12, throwResistance 2500, kein Snap, Richtung folgt dem letzten Wurf, Halt bei Hover und Drag",
   "kartenbreite": "max(200px, clamp(17vw, min(24vw, 37svh), 24vw)); Telefon 62vw; Format 4:5",
   "abstand": "clamp(14px, 1.6vw, 24px)",
   "greifer": "Kreis 84 px folgt der Maus mit lerp 0.2, beim Drücken scale 0.78"
  },
  "ausloeser": "ziehen",
  "touch": "Wischen mit dem Finger, Draggable lässt vertikales Scrollen durch (allowNativeTouchScrolling). Kein Greifer-Kreis, Pfeil-Buttons 40 px. Karten 62vw breit, Nachbarn sichtbar.",
  "reduziert": "Kein Schwung beim Loslassen, sofortiges Einrasten. Laufband steht, Neigung und Parallaxe aus. Pfeile springen mit 200 ms Blende (100 ms aus, 100 ms ein). Zähler ohne Rollen, Bildunterschrift 200 ms eingeblendet.",
  "korrekturen": {
   "beschreibung": "Eine Reihe von Slides läuft ohne Anfang und Ende. Eine einzige Zahl (die x-Position eines unsichtbaren Proxys) bestimmt alles: Jeder Slide sitzt bei i mal Slidebreite plus Position, per Modulo in die Gesamtbreite gefaltet. Wer zieht, bewegt den Proxy mit Draggable 1:1. Beim Loslassen übernimmt InertiaPlugin den Schwung, und eine Snap-Funktion rundet die natürliche Landeposition auf den nächsten Slide. Pfeile und Tasten springen per Tween zum Nachbarn. Zähler und Bildunterschrift folgen dem aktiven Slide.",
   "warum_es_wirkt": "Die Reihe fühlt sich an wie ein Gegenstand: Sie folgt dem Finger ohne Verzug und gleitet glaubwürdig aus. Das Einrasten schafft danach wieder Ordnung. Weil es kein Ende gibt, entsteht kein Gefühl von Begrenzung.",
   "wann_einsetzen": "Für Projektreihen, Produktkollektionen, Teamfotos, Referenzlogos und Stimmen von Kunden. Überall dort, wo man stöbern soll und nicht der Reihe nach lesen muss.",
   "wann_nicht": "Bei weniger als vier Elementen. Wenn die Reihenfolge verbindlich ist, etwa bei Schritten oder Preisen. Wenn Karten Formularelemente enthalten, denn dann konkurrieren Ziehen und Klicken.",
   "varianten": [
    "Einrasten: aktiver Slide in der Mitte, Nachbarn gedimmt, Wurf endet immer auf einem Slide",
    "Tempo: die Reihe neigt sich beim schnellen Ziehen (skewX nach Geschwindigkeit), das Bild im Slide läuft 10 bis 20 Prozent des Wegs gegen",
    "Laufband: läuft von selbst weiter, lässt sich greifen und werfen und kehrt danach in seine Bewegung zurück, in Richtung des letzten Wurfs",
    "Scroll-gekoppelt: Mausrad oder Trackpad treiben dieselbe Position (GSAP Observer)"
   ],
   "umsetzung": "Draggable auf ein Proxy-Element, nicht auf die Slides. Die Proxy-x-Position ist die Wahrheit; die Slides werden pro Frame daraus gesetzt (Modulo-Wrap) oder über den GSAP-Helfer horizontalLoop als Zeitleiste geführt. Snap rechnet in Slidebreiten, so wählt der Wurf automatisch den kürzesten Weg über den Loop-Rand. Fallstricke: bei Resize Breiten neu messen und die Position im Verhältnis umrechnen. Bewegung unter etwa 10 px als Klick werten und den letzten Snap behalten. Bilder mit draggable=false und user-select: none. Vor jedem eigenen Tween den Proxy auf die aktuelle Position setzen, sonst springt er. Jeder Pfeil-Button braucht ein eigenes aria-label.",
   "mobil": "Draggable funktioniert mit Touch. Vertikales Scrollen der Seite darf nicht blockiert werden: allowNativeTouchScrolling bzw. lockAxis. Alternative auf Mobilgeräten: natives overflow-x mit scroll-snap.",
   "reduzierte_bewegung": "Kein Autoplay, kein Schwung, keine Neigung. Beim Loslassen sofort einrasten. Navigation als Sprung oder mit kurzer Blende von 200 ms.",
   "barrierefreiheit": "Container mit role=region und aria-roledescription=carousel, jeder Slide als Gruppe mit aria-label \"n von m\". Pfeiltasten und sichtbare Buttons mit eigenen Labels. Slides außerhalb des Bildes mit aria-hidden oder inert. Läuft die Reihe von selbst, braucht sie einen Pause-Button (WCAG 2.2.2)."
  },
  "geprueft": "31.10.2026",
  "notiz": "Portfolio-Reihe mit acht CecoDesign-Marken, aktiver Slide mittig. Drei Varianten: Einrasten (Osmo-Werte), Tempo (Neigung und Bildparallaxe, eigene Werte), Laufband (Trionn-Werte, mit Pause-Button). Eigene Wrap-Funktion statt horizontalLoop, ohne Klone. Greifer-Kreis als Maus-Zeiger, Fortschrittsspur läuft mit. Vorführung: gedachter Greifer zieht und wirft nach links und rechts, danach zwei Klicks auf den Weiter-Pfeil. Bilder 01.11.2026: eigene Bilder statt Portfolio. Zugang 02.11.2026: --leise Alpha .56 → .66 (5,4:1); Zählermaske height 1lh statt 1em und Ziffern im Grid statt absolut (min-width 1.14em), bei Textabständen 1.4.12 nicht mehr abgeschnitten; Kontrastmodus-Rahmen für Knöpfe. Offen: Nicht aktive Karten mit opacity .42 (Kern des Effekts) bleiben unter 4,5:1."
 }
}
