{
 "$schema": "../../schema.json",
 "schema": "fundus/1",
 "id": "zahlen-odometer",
 "name": "Rollende Ziffern (Zahlen-Ticker / Odometer)",
 "name_en": "Number odometer / animated number flow / Number ticker / rolling digits / animated number",
 "kurz": "Kennzahlen eines Gestaltungsateliers rollen beim Jahreswechsel Stelle für Stelle in die neue Zahl, die Richtung folgt dem Trend.",
 "kategorie": "Schrift-Animationen",
 "kategorie_slug": "schrift-animationen",
 "kategorie_nr": 6,
 "bau_chat": "C1",
 "prioritaet": "A",
 "trendstatus": "etabliert",
 "belegstatus": "belegt",
 "website_belege": 2,
 "stimmung": [
  "präzise",
  "verspielt"
 ],
 "stimmung_roh": [
  "präzise",
  "technisch",
  "vertrauenswürdig",
  "lebendig"
 ],
 "technik": [
  "css",
  "vanilla-js",
  "gsap",
  "scrolltrigger",
  "motion"
 ],
 "technik_gruppen": [
  "css",
  "js",
  "gsap",
  "andere"
 ],
 "leistungskosten": "niedrig",
 "steckbrief": {
  "beschreibung": "Eine Zahl wird in Ziffern zerlegt. Jede Ziffer ist eine senkrechte Spalte 0–9 hinter einer Maske. Ändert sich der Wert, dreht jede Spalte zur Zielziffer. Die Richtung folgt dem Trend: steigt der Wert, rollt es nach oben. Neue oder entfallende Stellen und Tausenderpunkte blenden ein und aus, die Breite wächst oder schrumpft mit. Die Maske ist oben und unten weich ausgeblendet, so rollen die Ziffern aus dem Nichts.",
  "warum_es_wirkt": "Die Zahl wird zum Ereignis, ohne kitschiges Hochzählen. Die mechanische Anmutung wirkt präzise: Man sieht, dass das System rechnet. Mit tabular-nums bleibt die Zahl dabei ruhig und typografisch sauber.",
  "wann_einsetzen": "Kennzahlen-Sektionen („120 Projekte“), Preisumschalter monatlich/jährlich, Warenkorbsummen, Zähler, Dashboards, Preloader-Prozent, Countdowns.",
  "wann_nicht": "Wenn die Zahl sofort exakt gelesen werden muss (Formulare, Tabellen, Finanzhandel). Bei Dutzenden Zahlen gleichzeitig. Bei Live-Werten, die sich ständig ändern: Das erzeugt Unruhe.",
  "varianten": [
   "Odometer-Spalten mit translateY, Richtung nach Trend (NumberFlow, Motion AnimateNumber, Osmo „Number Odometer“)",
   "Durchlaufen: untere Stellen laufen sichtbar durch die Zwischenwerte (NumberFlow continuous)",
   "Klassisches Hochzählen vom alten zum neuen Wert per Tween, formatiert mit Intl.NumberFormat",
   "Nur CSS: @property --num mit syntax '<integer>' und counter(), nur ganze Zahlen",
   "Preloader 0–100 % in großer Display-Typo",
   "Scramble-Zahlen: Zufallsziffern, die einrasten",
   "Mikroanimation bei Wertänderungen (Preisumschalter, Like-Zähler)"
  ],
  "umsetzung": "Pro Ziffer eine Zelle mit Streifen: <span class='stelle'><span class='streifen'>0…9</span></span>. .stelle { height: 1lh; overflow: hidden; mask-image: linear-gradient(transparent, #000 14%, #000 86%, transparent) }. .streifen { transform: translateY(calc(var(--d) * -1lh)); transition: transform 750ms cubic-bezier(0, 0, 0.58, 1) }. Stellen nach Stellenwert von rechts verschlüsseln, damit Tausenderpunkte und neue Stellen sauber ein- und ausblenden (Opacity 350 ms, Breite 750 ms). Stellen mit transition-delay staffeln, Einer zuerst (30–60 ms). Für den Überlauf 9 → 0 in Trendrichtung den Streifen mehrfach wiederholen (z. B. 5 × 0–9) und vor jedem Lauf unsichtbar um 10 Zellen in den mittleren Block zurücksetzen. Trend = Math.sign(neu − alt). font-variant-numeric: tabular-nums verhindert Breitenzucken; Laufweite nicht in der Zelle setzen (overflow schneidet die Glyphe), sondern als Rand. Formatierung mit Intl.NumberFormat. Nur-CSS-Zähler: @property --num { syntax: '<integer>'; initial-value: 0; inherits: false } .c { counter-reset: n var(--num); transition: --num 1.2s } .c::after { content: counter(n) }. Nachkommastellen dann separat.",
  "mobil": "Unverändert. Hauptzahl in vw-Größe so wählen, dass die längste Zahl mit allen Stellen auf 390 px passt.",
  "reduzierte_bewegung": "Zielwert sofort zeigen, höchstens 100 ms überblenden. NumberFlow beachtet die Einstellung automatisch (respectMotionPreference).",
  "barrierefreiheit": "Ziffernspalten aria-hidden. Den echten Wert einmal zugänglich machen (aria-label oder visuell versteckter Text). Bei Wertänderungen aria-live='polite' nur mit dem Endwert ansagen, nie mit Zwischenwerten."
 },
 "messwerte": {
  "easing": "ease-out bzw. Spring",
  "dauer_ms": "750 (Ziffern-Spin/Transform), 350 (Opacity)",
  "stagger_ms": "30–60 je Stelle (typisch)",
  "distanz": "1em pro Ziffer",
  "sonstiges": "Werte aus NumberFlow-Beispielen, keine Bibliotheks-Defaults",
  "herkunft": "beobachtet",
  "quelle": "https://number-flow.barvian.me/",
  "aus_eintrag": [
   "number-odometer"
  ]
 },
 "kurve": {
  "bezier": [
   0.0,
   0.0,
   0.58,
   1.0
  ],
  "css": "cubic-bezier(0, 0, 0.58, 1)",
  "name": "ease-out",
  "dauer_ms": 750
 },
 "gesehen_bei": [
  {
   "seite": "NumberFlow",
   "url": "https://number-flow.barvian.me/",
   "auszeichnung": "",
   "beobachtung": "Ziffern drehen per Digit-Looping, Masken-Fade an den Rändern, Layout per Transform; Beispiele mit 750 ms für transform/spin und 350 ms ease-out für opacity; trend = Math.sign(neu − alt); respectMotionPreference standardmäßig true.",
   "art": "demo"
  },
  {
   "seite": "Motion+ AnimateNumber",
   "url": "https://motion.dev/docs/react-animate-number",
   "auszeichnung": "",
   "beobachtung": "2,5 kB-Komponente, Intl.NumberFormat-Formatierung, auf Layout-Animationen aufgebaut.",
   "art": "artikel"
  },
  {
   "seite": "Osmo – Number Odometer",
   "url": "https://www.osmo.supply/resource/number-odometer",
   "auszeichnung": "",
   "beobachtung": "Als hervorgehobene Ressource gelistet (Seite selbst nicht abrufbar).",
   "art": "demo"
  },
  {
   "seite": "Motion Examples: Number counter / Number trend / Price switcher",
   "url": "https://motion.dev/examples/react-number-trend",
   "auszeichnung": "",
   "beobachtung": "Offizielle AnimateNumber-Beispiele inkl. Formatierung, Engagement-Stats und Slider.",
   "art": "demo"
  },
  {
   "seite": "Motion Examples: Number formatting",
   "url": "https://motion.dev/examples/vue-number-formatting",
   "auszeichnung": "",
   "beobachtung": "Formatiertes Rollen von Zahlen.",
   "art": "demo"
  },
  {
   "seite": "Ramp",
   "url": "https://ramp.com/",
   "auszeichnung": "",
   "beobachtung": "Live-HTML enthält <number-flow-react> (NumberFlow-Web-Component mit Shadow DOM) mit tabular-nums für Prozent-Kennzahlen.",
   "art": "website"
  },
  {
   "seite": "Dub",
   "url": "https://dub.co/",
   "auszeichnung": "",
   "beobachtung": "Startseite: Klick-Statistik als <number-flow-react aria-label='7.3K' role='img'> – rollende Ziffern über NumberFlow.",
   "art": "website"
  }
 ],
 "tutorials": [
  {
   "titel": "NumberFlow",
   "url": "https://number-flow.barvian.me/"
  },
  {
   "titel": "Motion+ AnimateNumber",
   "url": "https://motion.dev/docs/react-animate-number"
  },
  {
   "titel": "CSS-Tricks – Animating Number Counters (@property)",
   "url": "https://css-tricks.com/animating-number-counters/"
  },
  {
   "titel": "Motion: Number counter",
   "url": "https://motion.dev/examples/vue-number-counter"
  }
 ],
 "kombinierbar_mit": [
  "split-mask-reveal",
  "scramble-decode",
  "gleitender-indikator",
  "like-herz-burst",
  "fortschrittsring",
  "zahlen-fakten-section"
 ],
 "urls": {
  "detail": "https://cecodesign.de/lab/fundus/schrift-animationen/zahlen-odometer/",
  "meta": "https://cecodesign.de/lab/fundus/schrift-animationen/zahlen-odometer/meta.json",
  "demo": "https://cecodesign.de/lab/fundus/schrift-animationen/zahlen-odometer/demo"
 },
 "herkunft": {
  "quelldateien": [
   "schriftanimation.json",
   "hover.json",
   "patch-belege-1.json"
  ],
  "pruefnotizen": [
   "patch-belege-1.json: 2 Produktionsbelege (beide NumberFlow); Messwerte bleiben die NumberFlow-Werte."
  ],
  "zusammengelegt_aus": [
   "number-odometer",
   "zahlen-ticker"
  ],
  "trendstatus_begruendung": "Konflikt etabliert (hover/Mikro) vs. aufsteigend (schriftanimation). Aufgelöst zu 'etabliert': das Zählwerk-Prinzip ist seit Jahren in UI und Kennzahlen-Sektionen verbreitet; Bibliotheken wie NumberFlow machen es nur einfacher.",
  "querverweis_kategorien": [
   "Mikroanimationen"
  ]
 },
 "bau": {
  "status": "fertig",
  "kurz": "Kennzahlen eines Gestaltungsateliers rollen beim Jahreswechsel Stelle für Stelle in die neue Zahl, die Richtung folgt dem Trend.",
  "demo": true,
  "abhaengigkeiten": [],
  "werte": {
   "easing": "cubic-bezier(0, 0, 0.58, 1) (ease-out, für Drehen, Breite, Opacity und Hochzählen)",
   "dauer_ms": {
    "drehen": 750,
    "breite_neue_stelle": 750,
    "opacity_neue_entfallende_stelle": 350,
    "hochzaehlen": 1200,
    "reduziert_ueberblenden": 100
   },
   "stagger_ms": "45 je Stelle, Einer zuerst (Verzögerung = Stellenwert × 45)",
   "distanz": "1 Zellenhöhe je Ziffer; Zelle = Zeilenhöhe 1.1em (Trend-Chip 1.25em)",
   "streifen": "50 Zellen (5 × 0–9), Ruhelage im mittleren Block ab Zelle 20; vor jedem Lauf unsichtbar um ±10 Zellen zurückgesetzt",
   "richtung": "trend = Math.sign(neu − alt); alle Stellen drehen in Trendrichtung, Überlauf 9 → 0 eingeschlossen",
   "durchlaufen": "Schritte je Stelle = Änderung des Präfixes ab dieser Stelle; ab 10 Schritten eine volle Runde zusätzlich (max. 19 Zellen)",
   "maske": "mask-image: linear-gradient(transparent, #000 14%, #000 86%, transparent)",
   "zahlformat": "Intl.NumberFormat('de-DE'), feste Nachkommastellen, signDisplay 'exceptZero' beim Trend, Minus als U+2212",
   "schrift": "Instrument Sans 500, font-variant-numeric: tabular-nums; Laufweite als margin-right -0.04em je Zelle (Hauptzahl), -0.025em (Kennzahlen)",
   "groessen": "Hauptzahl clamp(76px, min(21vw, 36vh), 320px), Telefon 26vw; Kennzahlen clamp(34px, 4.6vw, 64px)",
   "jahres_strich": "translate und width 350 ms, gleiche Kurve",
   "projektbild": "opacity 350 ms, scale 1.06 → 1 in 750 ms"
  },
  "ausloeser": "klick",
  "touch": "Identisch: Tippen auf Jahr oder Variante. Keine Hover-Abhängigkeit. Auf dem Telefon Hauptzahl 26vw, Projektbild als Daumenbild neben der Bildunterschrift, Kennzahlen zweispaltig.",
  "reduziert": "Ziffern springen ohne Drehen auf den Zielwert, die ganze Zahl blendet in 100 ms von 25 % auf 100 % Deckkraft. Keine Breiten-, Bild- oder Pfeilanimation.",
  "korrekturen": {
   "beschreibung": "Eine Zahl wird in Ziffern zerlegt. Jede Ziffer ist eine senkrechte Spalte 0–9 hinter einer Maske. Ändert sich der Wert, dreht jede Spalte zur Zielziffer. Die Richtung folgt dem Trend: steigt der Wert, rollt es nach oben. Neue oder entfallende Stellen und Tausenderpunkte blenden ein und aus, die Breite wächst oder schrumpft mit. Die Maske ist oben und unten weich ausgeblendet, so rollen die Ziffern aus dem Nichts.",
   "warum_es_wirkt": "Die Zahl wird zum Ereignis, ohne kitschiges Hochzählen. Die mechanische Anmutung wirkt präzise: Man sieht, dass das System rechnet. Mit tabular-nums bleibt die Zahl dabei ruhig und typografisch sauber.",
   "wann_einsetzen": "Kennzahlen-Sektionen („120 Projekte“), Preisumschalter monatlich/jährlich, Warenkorbsummen, Zähler, Dashboards, Preloader-Prozent, Countdowns.",
   "wann_nicht": "Wenn die Zahl sofort exakt gelesen werden muss (Formulare, Tabellen, Finanzhandel). Bei Dutzenden Zahlen gleichzeitig. Bei Live-Werten, die sich ständig ändern: Das erzeugt Unruhe.",
   "varianten": [
    "Odometer-Spalten mit translateY, Richtung nach Trend (NumberFlow, Motion AnimateNumber, Osmo „Number Odometer“)",
    "Durchlaufen: untere Stellen laufen sichtbar durch die Zwischenwerte (NumberFlow continuous)",
    "Klassisches Hochzählen vom alten zum neuen Wert per Tween, formatiert mit Intl.NumberFormat",
    "Nur CSS: @property --num mit syntax '<integer>' und counter(), nur ganze Zahlen",
    "Preloader 0–100 % in großer Display-Typo",
    "Scramble-Zahlen: Zufallsziffern, die einrasten",
    "Mikroanimation bei Wertänderungen (Preisumschalter, Like-Zähler)"
   ],
   "umsetzung": "Pro Ziffer eine Zelle mit Streifen: <span class='stelle'><span class='streifen'>0…9</span></span>. .stelle { height: 1lh; overflow: hidden; mask-image: linear-gradient(transparent, #000 14%, #000 86%, transparent) }. .streifen { transform: translateY(calc(var(--d) * -1lh)); transition: transform 750ms cubic-bezier(0, 0, 0.58, 1) }. Stellen nach Stellenwert von rechts verschlüsseln, damit Tausenderpunkte und neue Stellen sauber ein- und ausblenden (Opacity 350 ms, Breite 750 ms). Stellen mit transition-delay staffeln, Einer zuerst (30–60 ms). Für den Überlauf 9 → 0 in Trendrichtung den Streifen mehrfach wiederholen (z. B. 5 × 0–9) und vor jedem Lauf unsichtbar um 10 Zellen in den mittleren Block zurücksetzen. Trend = Math.sign(neu − alt). font-variant-numeric: tabular-nums verhindert Breitenzucken; Laufweite nicht in der Zelle setzen (overflow schneidet die Glyphe), sondern als Rand. Formatierung mit Intl.NumberFormat. Nur-CSS-Zähler: @property --num { syntax: '<integer>'; initial-value: 0; inherits: false } .c { counter-reset: n var(--num); transition: --num 1.2s } .c::after { content: counter(n) }. Nachkommastellen dann separat.",
   "mobil": "Unverändert. Hauptzahl in vw-Größe so wählen, dass die längste Zahl mit allen Stellen auf 390 px passt.",
   "reduzierte_bewegung": "Zielwert sofort zeigen, höchstens 100 ms überblenden. NumberFlow beachtet die Einstellung automatisch (respectMotionPreference).",
   "barrierefreiheit": "Ziffernspalten aria-hidden. Den echten Wert einmal zugänglich machen (aria-label oder visuell versteckter Text). Bei Wertänderungen aria-live='polite' nur mit dem Endwert ansagen, nie mit Zwischenwerten."
  },
  "geprueft": "31.10.2026",
  "notiz": "Jahresbilanz des erfundenen Ateliers Kranich: Reiter 2024/2025/2026 rollen Hauptzahl, Trend-Chip (mit Vorzeichen) und drei Kennzahlen; das Projekt des Jahres blendet mit. Umschalter Odometer / Durchlaufen / Hochzählen. Zeigt neue Stelle (9.870 → 11.215), entfallende Stelle, Vorzeichenwechsel und Dezimalkomma. Unterbrechung mitten im Lauf wird sauber weitergedreht. Reines Vanilla-JS ohne Abhängigkeiten. Vorführung: Jahre im 2,6-s-Takt, je Runde nächste Variante. Bilder 01.11.2026: eigene Bilder statt Portfolio. Zugang 02.11.2026: --leise .56 → .64 (5,0:1), Kontrastmodus-Rahmen für Knöpfe."
 }
}
