About this animation
A zodiac picker with morphing star charts and a draggable forecast sheet, with configurable forecasts, title, fonts, and accent color.
Why this one
Instead of replacing two pictures with a crossfade, persistent stars follow staggered curved flights. Connections retract, rebuild, and send a finishing sparkle through their endpoints. The selector uses miniature constellation charts rather than zodiac glyphs.
How it works
onLayoutmeasures the host. Original normalized coordinates place charts inside a 76% width × 42% height sky area.- A continuous selector position drives horizontal dragging, miniature charts, and background parallax. Release projects velocity and settles with a nearly critical spring.
- A selection snapshots the currently rendered positions, so interrupted flights start where the stars actually are. Extra stars originate at the nearest visible star; removed stars approach the nearest destination and fade.
- One transition clock retracts old paths in 200 ms, staggers stars by 30 ms, draws new paths in 300 ms after arrival, and triggers an endpoint-order sparkle. The default last star lands at 800 ms.
- A separate interruptible sheet progress shrinks the constellation to 45% and moves the sheet from 91% to 32% of the container height. The same value staggers five forecast bars.
- The demo owns autoplay: Cancer → Leo → Virgo → Scorpio at 1.6-second intervals, opens the sheet, changes tabs, closes, and repeats. Direct touch cancels the loop.
Install
npx expo install @shopify/react-native-skia expo-blur expo-linear-gradient react-native-gesture-handler react-native-reanimated react-native-workletsMount under GestureHandlerRootView. Configure Reanimated/worklets as required by your Expo project. Web hosts must initialize CanvasKit before mounting Skia components (for example with Skia's WithSkiaWeb wrapper). No assets, network requests, or external theme imports are needed by the component.
Usage
import ConstellationMorphPicker from './constellation-morph-picker';
export default function SkyScreen() {
return <ConstellationMorphPicker />;
}import { useRef } from 'react';
import { ConstellationMorphPicker, type ConstellationMorphPickerRef } from './constellation-morph-picker';
export function CustomSky() {
const sky = useRef<ConstellationMorphPickerRef>(null);
return (
<ConstellationMorphPicker
ref={sky}
title="Your evening sky"
initialIndex={7}
accentColor="#B7C1FF"
morphDuration={600}
fontFamily="YourSans"
titleFontFamily="YourSerif"
monoFontFamily="YourMono"
onIndexChange={(index) => saveSelection(index)}
/>
);
}The ref exposes select(index), open(), close(), setTab(index), and reset(). Sign indices follow Aries through Pisces; tab indices follow Today, Tomorrow, Weekly. Load custom fonts in the host.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | Explore the night sky | Header copy. |
| initialIndex | number | 3 | Initial sign, clamped to 0–11. |
| accentColor | string | #A5B4FC | Chart halo and selector accent. |
| morphDuration | number | 530 | Per-star flight duration in ms, plus 30 ms stagger. |
| forecasts | [Forecast, Forecast, Forecast] | Original editorial copy | Titles, bodies, and five percentage values for each tab. |
| fontFamily | string | System | Interface font. |
| titleFontFamily | string | System | Display font. |
| monoFontFamily | string | System | Date and percentage font. |
| onIndexChange | (index: number) => void | — | Sign selection callback. |
| onSheetChange | (open: boolean) => void | — | Sheet destination callback. |
| onInteraction | () => void | — | Direct interaction callback, used to pause autoplay. |
| style | StyleProp<ViewStyle> | — | Root style, with flex: 1 by default. |
| testID | string | — | Root testing identifier. |
Forecast contains title, body, and values: [number, number, number, number, number] in Career, Love, Family, Health, Luck order. Keep copy concise on smaller screens. The exported CONSTELLATIONS data contains 12 original charts, each with 7–10 stars and 6–9 segments.
Compatibility
Built for Expo SDK 58, React Native 0.88.0, Reanimated 4.7.1, worklets 0.13.0, Gesture Handler 3.3, and Skia 2.14.0. All dependencies are already in this Expo project. Supports iOS, Android, and web. Expo Go with the SDK-compatible modules is supported. Android 12+ uses a shared BlurTargetView; older Android versions use the tinted fallback.
Accessibility
Every sign, tab, and sheet handle has a button role, label, and selection/expansion state. Screen reader activation provides a tap alternative to dragging. Sign, sheet, and tab changes are announced. Foreground copy uses high contrast, and bars include spoken percentages. Hidden sheet content and the covered selector are excluded from the accessibility tree.
Reduced motion disables star flights, sparkles, twinkling, parallax, text blur, pressure scaling, and glass blur. Sign changes use a 200 ms fade; tabs switch directly, and sheet transitions use 200 ms timing.
Icons: Lucide (ISC), copied from the repository kit. The Aster demo uses the kit's sparkle tile, tinted in the selector's lavender accent over a midnight-indigo gradient; it is separate from the reusable component.



