Skip to content
Native Animation
Infinite Zoom Intro animation preview
Onboarding

Infinite Zoom Intro

React Native Onboarding Animation with Infinite Zoom

A cinematic onboarding sequence that travels through nested photographic worlds before revealing nearby friends and a bold brand screen.

$9 for this animation

Checkout opens soon. Leave your email and we will tell you the moment you can buy it.

One email when checkout opens. No spam.

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.

npx nativeanimation add infinite-zoom-intro

About this animation

A React Native onboarding animation can travel from a broad photographic view into a close destination before revealing its final action. This component moves through nested image levels with one continuous Reanimated journey that also controls titles, friend markers, distance counters, the final badge, and the call to action. Its camera accelerates, cruises, and decelerates across the whole sequence rather than restarting speed at each image handoff. Use it for a nearby-community introduction, location discovery, a photographic narrative, or a staged first-run journey. Supply at least two image levels and optionally up to three friends, then customize the final name, action label, accent, fonts, and travel time per level. Connect completion and action callbacks, or replay and skip through the forwarded ref.

When to use it

  • Introduce a nearby community.
  • Travel through photographic onboarding levels.
  • Reveal people at a final destination.
  • Build a staged location-discovery introduction.

A cinematic onboarding sequence that travels through nested photographic worlds before revealing nearby friends and a bold brand screen.

How it works

  1. One continuous journey shared value drives the complete sequence, so images, titles, friend markers, counters, the brand screen, and the CTA cannot drift onto separate clocks.
  2. The camera uses a continuous velocity profile: a gentle acceleration, a constant-speed cruise, and a long deceleration into the final image. Every layer reads the same camera position, which removes speed resets at level boundaries.
  3. Titles are derived directly from that camera position and cross-fade while traveling a short distance, with no React state update or independent animation between levels.
  4. After the camera stops, friend markers settle in with a restrained spring-shaped path. The completed scene then holds before the brand badge and CTA enter.
  5. Reduced Motion keeps the narrative order but replaces scaling and overshoot with cross-fades and shorter holds.

Timing

levelSeconds controls the camera travel time per transition. With the four-level demo and the default 1.8, the timing is:

PhaseDurationMotion
Camera travel3 × 1.8s = 5.4sFirst 14% accelerates smoothly, the middle cruises at constant speed, and the final 32% decelerates continuously.
Arrival pause150msThe final photograph becomes completely still before markers enter.
Friend markers500ms each, staggered by 100msThree markers finish in 700ms; their position, scale, and distance counter share the main journey.
Final breath650msThe complete last scene rests with no new movement.
Brand and CTA700msThe brand surface fades in first; the CTA follows during the latter 62% of the reveal.

The default four-level sequence therefore finishes in 7.6s. A different number of levels changes only the camera-travel portion. Reduced Motion uses 250ms marker and reveal phases, a 40ms marker stagger, and a 250ms final breath.

Why this one

Many infinite-zoom intros animate each layer as a separate clip, creating tiny pauses or acceleration resets that become especially noticeable near the end. This implementation treats the entire piece as one choreographed journey, preserves velocity through every photographic handoff, and gives the destination enough time to settle before asking the viewer to act. The restrained type movement, soft depth, single accent, and delayed white CTA keep the cinematic effect legible instead of turning the finish into a pileup of competing animations.

Install

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

On web, load Skia before rendering this component. The Native Animation catalog handles that asynchronous setup at its app boundary.

Usage

import InfiniteZoomIntro from './InfiniteZoomIntro';

const levels = [
  { image: require('./overview.jpg'), title: 'The world' },
  { image: require('./neighborhood.jpg'), title: 'Close to home' },
];

export function IntroScreen() {
  return <InfiniteZoomIntro levels={levels} />;
}

Customize the pacing, people, typography, and final action or control playback through its ref:

import { useRef } from 'react';
import InfiniteZoomIntro, { type InfiniteZoomIntroRef } from './InfiniteZoomIntro';

export function SocialIntro() {
  const introRef = useRef<InfiniteZoomIntroRef>(null);

  return (
    <InfiniteZoomIntro
      accentColor="#5B4BFF"
      brand="Together"
      ctaLabel="Find my circle"
      fontFamily="YourSansFont"
      friends={friends}
      levelSeconds={2.1}
      levels={levels}
      onCtaPress={() => continueOnboarding()}
      onFinish={() => trackIntroComplete()}
      ref={introRef}
      titleFontFamily="YourDisplayFont"
    />
  );
}

The forwarded ref exposes replay() and skip().

Props

PropTypeDefaultDescription
levelsZoomLevel[]RequiredTwo or more photographic levels, ordered from outermost to closest.
friends{ avatar: ImageSourcePropType; distance: string }[][]Up to three people revealed on the last level.
brandstring'Nearby'Name inside the final badge.
ctaLabelstring'Get me in'Fixed bottom action label.
accentColorstring'#3D5AFE'Color used by distance pills, the action, and the final screen.
levelSecondsnumber1.8Duration of each zoom segment in seconds.
titleFontFamilystringSystem fontFont used by level titles and the brand.
fontFamilystringSystem fontFont used by captions, distances, and the action.
onCtaPress() => void—Called when the bottom action is pressed.
onFinish() => void—Called after the final brand screen fades in.
styleStyleProp<ViewStyle>—Outer-container style.
testIDstring—Test identifier for the outer container.

Compatibility

  • Expo SDK 57
  • React Native 0.86
  • Reanimated 4.5, Worklets 0.10, and React Native Skia 2.6
  • iOS: supported, not yet verified on a device
  • Android: supported, not yet verified on a device
  • Web: supported, verified by the project build
  • Works in Expo Go because its native dependencies are included in Expo SDK 57

Accessibility

The action is exposed as a labeled button, titles are announced as headings, and friend markers include their distance. With Reduce Motion enabled, image levels cross-fade without scaling, markers fade without bouncing, and the badge remains still.

FAQ

How many image levels does the infinite zoom intro need?
Supply at least two levels, ordered from outermost to closest. Each level contains its image and title; friends can add up to three avatars and distance labels to the final scene.
Can I change the zoom speed or skip the introduction?
Yes. levelSeconds sets travel time per transition, while the ref exposes replay and skip. onFinish runs after the final screen fades in and onCtaPress handles the action.
Does the onboarding zoom support Reduce Motion?
Yes. Image levels crossfade without scaling, markers fade without bouncing, and the badge stays still. The narrative order remains intact with shorter holds.