Skip to content
Native Animation
Impact numbers scroll animation preview

This preview uses fictional demo content. See the props below for the customization options available in this component.

npx nativeanimation add impact-numbers-scroll
Skia

Impact numbers scroll

A scroll-driven impact report with morphing particles and rolling statistics, with configurable chapters, title, fonts, and particle drift.

$9 for this animation

Add to your project

Copy the component and its assets into your app with the Native Animation CLI, or paste the agent prompt into Claude Code, Codex or Cursor once the MCP server is connected.

About this animation

A scroll-driven impact report with morphing particles and rolling statistics, with configurable chapters, title, fonts, and particle drift.

Why this one

The same cloud becomes a bottle, a breaking wave, twelve swimming fish, and finally “2.4M.” The statistics become the visual story instead of sitting beside a generic counter. Local ocean photography, chapter accents, and a real glass footer give the demo a coherent world.

How it works

  1. Sample filled Skia paths once into four typed destination arrays.
  2. Derive one continuous chapter progress from the measured container height and native scroll events.
  3. Hold each particle pose for the first and last 20% of each segment. Smoothstep interpolation and individual perpendicular bends reorganize the cloud.
  4. Draw 15 batched Points nodes in one Canvas. Exactly 20% of particles carry the chapter accent; radii range from 1.2 to 2.4 points.
  5. Animate numeric values for 900 ms on chapter entry. Each digit column advances only during its carry, with distance fading and a clipped line box.
  6. Stack photos with entrance opacity, separate title entrance/exit windows, and place the final action inside the scroll content. The demo drives the scroll through the ref every 2.6 seconds and stops on touch.

Install

npx expo install @shopify/react-native-skia expo-blur expo-image expo-linear-gradient react-native-reanimated react-native-worklets

Copy this folder without demo/. Load your fonts in the host. On web, initialize CanvasKit before mounting this component; an Expo host can use Skia’s WithSkiaWeb with a lazy component import. The catalog must register this Skia piece through its existing lazy Skia loader.

Icons: Lucide (ISC). Copied paths are in icons.ts; the source license is in the repository kit.

Usage

import ImpactNumbersScroll from './impact-numbers-scroll';

export default function Report() {
  return <ImpactNumbersScroll onJoin={() => openRefillSignup()} />;
}
const report = useRef<ImpactNumbersScrollRef>(null);

<ImpactNumbersScroll
  ref={report}
  chapters={fourChapters}
  reportTitle="Annual impact / 2026"
  fontFamily="YourSans"
  serifFontFamily="YourSerif"
  italicFontFamily="YourItalic"
  monoFontFamily="YourMono"
  counterDuration={900}
  driftAmplitude={1.5}
  ctaLabel="Start refilling"
  onJoin={openRefillSignup}
/>;
// Call from an event or a timer:
report.current?.scrollToChapter(2);

Props

PropTypeDefaultDescription
chaptersreadonly ImpactChapter[]Four neutral chaptersSupply exactly four; silhouettes stay in their defined order.
reportTitlestringImpact reportUpper-left label.
footerReactNodeEvery refill countsContent inside the blurred material.
ctaLabelstringMake your next refill countFinal button and accessibility label.
onJoin() => voidundefinedFinal button action.
onChapterChange(index: number) => voidundefinedChapter-entry callback on JS.
onInteraction() => voidundefinedTouch/drag callback for stopping host playback.
fontFamilystringsystemBody font.
serifFontFamilystringsystemTitle font.
italicFontFamilystringsystemAccent title font.
monoFontFamilystringsystemTabular statistics and chapter labels.
counterDurationnumber900Counter entrance duration, milliseconds.
driftAmplitudenumber1.5Ambient displacement, points.
snapToChaptersbooleantrueNative snapping; never enabled on web.
styleStyleProp<ViewStyle>undefinedRoot style; give the parent a height.
testIDstringundefinedRoot test identifier.

ImpactChapter contains value, optional suffix, eyebrow, title, ending, body, accent, and optional local image. Decimal statistics support one decimal place. The default compact final target is 2.4M.

Ref methods: scrollToChapter(index) animates the actual scroll position; reset() returns to the first chapter and replays condensation; fade(hidden) controls the loop’s black transition.

Compatibility

Built for Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, worklets 0.13.0, and Skia 2.14.0. Uses the SDK 58 Android BlurTargetView API. Compatible with the installed Expo Go stack; custom hosts need the same native modules in their build. Web requires CanvasKit initialization.

Accessibility

Titles use the header role, counters expose their complete values, and both actions have button roles, labels, and at least 44-point targets. Normal scrolling and the first-screen next button provide alternatives. Reduced motion removes rain, breathing, swimming, and animated digit rolling; chapter text fades in 200 ms with stationary silhouettes. No parallax, zoom, or velocity trails are used.

Layout

The layout is calculated from onLayout, with no content before measurement. At 390×844 and 320×694, the particle area occupies the upper half; statistics begin at 56.5% height, followed by two editorial lines and evidence. The large bottle count scales down only as needed to fit narrow screens. The upper-right viewer close area stays empty. The first 1.5 seconds condense rain into the bottle while the counter rolls. Light is rendered by particles; no solid block simulates a glow.

Customization notes

Set chapters[].accent to theme the chapter highlights.