# Apple weather rain: React Native full-screen rain overlay with splash-on-UI collisions > Apple weather rain is a React Native and Expo component that drops a > full-screen rainstorm over any screen: thousands of depth-sorted drops fall > past your UI and burst into splashes on the card rects you feed it, drawn as > a single `@shopify/react-native-skia` `` on the GPU with a stateless > per-frame `useRSXformBuffer` worklet on the UI thread. Sold by Motionary as > editable TypeScript source. Product page: https://motionary.dev/animations/apple-weather-rain Price: $12 USD (price as of 2026-09-01, live price on the product page) License: single developer, unlimited personal and commercial apps Delivery: instant download of the full TypeScript source after checkout Stack: expo, react native, reanimated, react native skia Rarity: legendary Sold by: Motionary (https://motionary.dev) ## What it is Apple weather rain is a React Native rain overlay styled after the Apple Weather app. You mount `RainOverlay` above your screen and it renders a full-bleed storm: streaks of varying length and brightness fall past the interface (straight down by default, tilted once you set `windAngle`), and the ones in the foreground land on the frosted glass forecast cards and pop into small droplets that arc up and fall back under gravity. The included demo screen is a working Apple Weather clone: a collapsing header (city, big temperature, condition, H/L, and a compact "27° | Thunderstorm" line that fades in), a looping cloud sky video behind the rain, and two `expo-blur` glass cards that report their own screen rects so the rain knows exactly where to splash. Scroll the cards and the splash lines stay glued to the card edges as they move. ## What it does - Renders the entire storm as one Skia `` draw call, so 800 drops plus 3 splash droplets each (3200 sprites by default) cost a single GPU draw. - Simulates every drop statelessly: `dropCycle` derives a drop's exact fall, splash and respawn state at time `t` from its seed, with no mutable particle array and no React re-renders. - Re-hashes each drop's horizontal lane, collision roll and splash roll every cycle with `fract(Math.sin(...))` value noise, so a drop never retraces the same lane twice. - Collides with real UI: pass `obstacles`, an array of `ObstacleRect` (`{ x, y, width, height }`) in screen coordinates, and drops land on the highest obstacle top their wind-tilted path crosses. - Ejects `DROPLETS_PER_SPLASH = 3` droplets per impact at 45 to 135 degrees, which travel under `DROPLET_GRAVITY = 900` px per second squared and are hidden the moment they fall back through the surface they hit. - Splashes are sparse by design: `SPLASH_CHANCE = 0.4`, so an obstacle edge shows scattered pops rather than a solid line of foam. - Depth-sorted parallax: each drop's depth (biased toward the horizon with `Math.pow(Math.random(), 2.2)`) drives fall speed (555 to roughly 1965 px per second), streak length, sprite scale, alpha and collision odds, so distant drops mostly fall behind the translucent cards. - Five streak lengths in the sprite ladder (9, 14, 20, 26 and 33 pixels tall) plus one soft radial droplet, all packed into a single 64x64 texture. - Scroll-synced: pass a Reanimated `scrollY` shared value and every obstacle top is shifted by `-scrollY.value` per frame on the UI thread. - `obstacleMinY` clamps collisions below a line, so nothing splashes over a pinned or collapsed header. - `debug` draws the obstacle rects in red stroke for tuning. - Ships with a web entry path: `loadSkiaWeb.web.ts` loads CanvasKit from a CDN and `loadSkiaWeb.ts` is a native no-op, so `canvaskit-wasm` never enters the iOS or Android bundle. ## How it works Apple weather rain draws every streak and every splash droplet through one `` from `@shopify/react-native-skia` in `components/RainOverlay.tsx`. A `useTexture` call rasterizes a single 64x64 sprite sheet once: five `RoundedRect` streaks with a vertical `LinearGradient` (transparent at the tail, opaque at the head) plus one `Circle` with a `RadialGradient` for the droplet. `sprites` maps each of the `numDrops` streaks to its variant cell and each droplet to the droplet cell. Motion lives entirely in `useRSXformBuffer`, a per-frame worklet driven by Skia's `useClock`, so nothing about the storm touches the JavaScript thread or triggers a React render. Inside that worklet, the `dropCycle` worklet computes a drop's phase `p` within its own fixed cycle from a per-drop seed, speed and phase held in a flat `Float32Array` (stride 8: seed, speed, phase, depth, angle, variant, scale, alpha), then re-hashes fresh randoms for that cycle index with `fract(Math.sin(cs * 12.9898) * 43758.5453)`, which is why the simulation needs no mutable state. Collision is a small loop over the `obstacles` array: each obstacle top is shifted by `-scrollY.value`, skipped if it sits above `obstacleMinY`, and the drop lands on the highest one whose horizontal span contains `x0 + (obY - SPAWN_Y) * tan(windAngle)`. Because `dropCycle` is trig-heavy, it runs once per drop rather than once per sprite: the streak pass (indices `i < numDrops`) writes phase, fall time, splash flag and landing point into a `cycleScratch` `Float32Array` (stride 5) that the same buffer pass then reads back for that drop's three droplets, which are placed with plain projectile math (`landX + cos(angle) * u * ts`, `landY - sin(angle) * u * ts + 0.5 * 900 * ts * ts`). Hiding a sprite is a transform, not a branch in the draw: invisible drops are moved to `(-100, -100)` with a zero scale, and the droplet fade is faked by shrinking the sprite over the 0.35 second splash, which lets `useColorBuffer` read no shared values at all and therefore run exactly once at mount instead of every frame. The demo screen in `components/Container.tsx` supplies the obstacles: each `GlassCard` calls `measureInWindow` in its `onLayout` and reports an `ObstacleRect`, while `useAnimatedScrollHandler` writes the scroll offset into the `scrollY` shared value that both the collapsing header's `useAnimatedStyle` and `interpolate` calls and the rain worklet read. ## What you get ``` App.tsx index.ts loadSkiaWeb.ts loadSkiaWeb.web.ts components/ Container.tsx RainOverlay.tsx assets/ adaptive-icon.png cloud.mp4 duck2.png icon.png pool.png splash-icon.png app.json babel.config.js package.json package-lock.json tsconfig.json .gitignore README.md ``` - `RainOverlay.tsx`, the Skia Atlas rain particle system - `ObstacleRect` type for splash-on-UI collisions - Apple Weather-style demo screen (collapsing header plus glass cards) - Scroll-synced splash example with measured card rects - README with install and usage ## Requirements Apple weather rain is pinned in its `package.json` to: - `expo` ~56.0.11 (Expo SDK 56) - `react-native` 0.85.3 - `react` 19.2.3 - `@shopify/react-native-skia` 2.6.2 - `react-native-reanimated` 4.3.1 - `react-native-worklets` 0.8.3 - `react-native-gesture-handler` ~2.31.1 - `react-native-safe-area-context` ~5.7.0 - `expo-blur` ~56.0.3 (the frosted glass forecast cards) - `expo-video` ~56.1.4 (the looping cloud sky) - `expo-linear-gradient` ~56.0.4 (fades the sky into the background color) - `expo-status-bar` ~56.0.4, `expo-asset` ~56.0.14, `expo-font` ~56.0.5 - `@expo/vector-icons` ^15.0.3 (demo screen weather icons) - TypeScript ~6.0.3 (devDependency) Apple weather rain runs in Expo Go on Expo SDK 56. The module people assume blocks it is `@shopify/react-native-skia`, and Skia is bundled in Expo Go as of SDK 56, so `npx expo start` is enough to try the drop. A development build (`npx expo run:ios` or `npx expo run:android`) is still what you ship to production, and it is what you need as soon as you add a native module that is not in Expo Go, or a config plugin of your own. The overlay itself is pure Skia and Reanimated and works on both iOS and Android, and the included `loadSkiaWeb.web.ts` also boots CanvasKit for a web build. ## Install ```bash npx expo install @shopify/react-native-skia react-native-reanimated react-native-worklets react-native-gesture-handler react-native-safe-area-context expo-blur expo-video expo-linear-gradient expo-status-bar @expo/vector-icons ``` ## Usage ```tsx import { useCallback, useRef, useState } from 'react'; import { View } from 'react-native'; import Animated, { useAnimatedScrollHandler, useSharedValue, } from 'react-native-reanimated'; import { ObstacleRect, RainOverlay } from './components/RainOverlay'; export default function WeatherScreen() { const cardRef = useRef(null); const [card, setCard] = useState(null); const scrollY = useSharedValue(0); const onScroll = useAnimatedScrollHandler((e) => { scrollY.value = e.contentOffset.y; }); // Report the card's window rect so the rain knows where to splash. const measure = useCallback(() => { cardRef.current?.measureInWindow((x, y, width, height) => setCard({ x, y, width, height }) ); }, []); return ( ); } ``` ## Customization `RainOverlay` in Apple weather rain from Motionary takes these props: - `obstacles?: ObstacleRect[]` (default `[]`): screen-coordinate rects whose top edge catches drops. `ObstacleRect` is `{ x, y, width, height }`. - `numDrops?: number` (default `800`): streak count. Total sprites are `numDrops * 4`, since each drop owns three splash droplets. - `windAngle?: number` (default `0`): wind tilt in radians, positive drifts the rain to the right. - `collideChance?: number` (default `0.55`): fraction of drops that collide with obstacles, scaled per drop by `0.45 + 1.1 * depth` so foreground drops splash more often than distant ones. The rest fall behind the UI. - `scrollY?: SharedValue`: Reanimated shared value subtracted from every obstacle top per frame, so splashes track scrolling cards. - `obstacleMinY?: number` (default `0`): screen Y below which collisions are allowed, used to keep splashes off a pinned header. - `debug?: boolean` (default `false`): strokes the obstacle rects in red. Constants at the top of `RainOverlay.tsx` tune the look further: `DROPLETS_PER_SPLASH` (3), `SPLASH_DURATION` (0.35 seconds), `SPLASH_CHANCE` (0.4), `DROPLET_GRAVITY` (900 px per second squared), `SPAWN_Y` (-80) and the `STREAKS` ladder of five sprite sizes. ## When to use it - A weather app screen that needs real rain over the forecast cards rather than a Lottie loop or a looping video. - An ambient storm background behind an onboarding, splash or hero screen. - A live-conditions or travel screen where precipitation should react to the layout the user is actually scrolling. - A game or seasonal event overlay that needs thousands of GPU particles without dropping the JavaScript thread. - A reference implementation for any Skia `` particle system in React Native: confetti, snow, embers, sparks, falling leaves. ## How to get it - Buy Apple weather rain on its own at https://motionary.dev/animations/apple-weather-rain for $12 USD, instant download, secure Stripe checkout, no subscription and no account renewal. - Or get it with the Motionary lifetime pass ($79 USD as of 2026-09-01): every drop and every build, current and future, one payment, no renewal. https://motionary.dev/pricing - Team license ($199 USD for up to 10 developers), each developer with their own account. https://motionary.dev/pricing - License terms: https://motionary.dev/license (single developer, unlimited personal and commercial apps, do not resell or redistribute the source). - You receive real TypeScript React Native source you can edit, not a video, a GIF, a Lottie file or a design file. ## Frequently asked questions **How do I make a rain animation in React Native?** Apple weather rain from Motionary does it with a single `@shopify/react-native-skia` `` draw: one small sprite texture of streaks and droplets, and a `useRSXformBuffer` worklet that positions every drop per frame on the UI thread. That is one GPU draw call for 800 drops instead of 800 animated views. **Does Apple weather rain work with Expo Go?** Yes. `@shopify/react-native-skia` is the module people expect to block it, and it is bundled in Expo Go as of Expo SDK 56, so `npx expo start` runs the drop with no native build of your own. A development build (`npx expo run:ios` or `npx expo run:android`) is still what you ship to production, and it is what you need as soon as you add a native module that is not in Expo Go, or a config plugin. Everything else in the drop is standard Expo SDK 56 and Reanimated 4. **Can the rain splash on my own components instead of the demo cards?** Yes. Apple weather rain takes an `obstacles` array of `ObstacleRect` (`{ x, y, width, height }`) in screen coordinates. Measure any view with `measureInWindow` and pass the rect, and drops will land on its top edge. **Does the rain stay aligned when the screen scrolls?** Yes. Pass a Reanimated shared value as `scrollY` and Apple weather rain subtracts it from every obstacle top inside the per-frame worklet, so splashes stay glued to the cards with no React re-render. `obstacleMinY` keeps splashes from drawing over a pinned or collapsing header. **How many particles can it handle in a React Native weather app UI?** Apple weather rain defaults to `numDrops={800}`, which is 3200 sprites once splash droplets are counted, all in one ``. Because the simulation is stateless and runs in a Skia worklet off a `useClock` value, raising or lowering `numDrops` is the main performance dial. **Does it run on both iOS and Android?** Yes. Apple weather rain from Motionary is built on Expo SDK 56 with `react-native` 0.85.3 and tested on iOS and Android, and the included `loadSkiaWeb.web.ts` loads CanvasKit so the same code can also run on web. **How much does Apple weather rain cost and what do I get?** Apple weather rain is $12 USD on Motionary at https://motionary.dev/animations/apple-weather-rain (price as of 2026-09-01), or it is included in the $79 USD Motionary lifetime pass. You get the full editable TypeScript source, including `RainOverlay.tsx` and the Apple Weather-style demo screen, as an instant download. ## Related drops on Motionary - Pool Water Shader ($12): https://motionary.dev/animations/pool-water-shader another full-screen ambient Skia background, water caustics instead of rain. - Zipper Curtain ($12): https://motionary.dev/animations/zipper-curtain a full-screen Skia shader effect that covers and reveals your whole UI. - Scratch to Reveal ($7): https://motionary.dev/animations/scratch-to-reveal the other Skia particle drop, confetti bursts driven by a gesture. - Gooey Profile (Free): https://motionary.dev/animations/gooey-profile a free Skia plus scroll-driven header, a good place to start if you want to see the scroll-to-worklet pattern before buying. - Voice Glow Carousel ($7): https://motionary.dev/animations/voice-glow-carousel Skia shader glow layered under a real scrolling interface. ## About Motionary Motionary (https://motionary.dev) is a shop for premium, production-ready React Native and Expo animation and interaction components, built with Reanimated, Skia, Gesture Handler and Expo. Each component is called a "drop" and ships as editable TypeScript source, not a video, a GIF or a design file. Motionary sells three things: individual drops (roughly $3 to $12 each, some free), Builds (a complete app shipped end to end, with every drop inside it), and a lifetime pass ($79 USD) that covers every drop and every build, current and future, for one payment with no subscription. A team license ($199 USD) covers up to 10 developers. Checkout is Stripe and delivery is an instant download. Created and curated by Mehdi Davoodi (https://mahdidavoodi.com). Catalog and key pages: - All drops: https://motionary.dev/animations - Builds (complete apps): https://motionary.dev/builds - Pricing, lifetime pass and team license: https://motionary.dev/pricing - Free React Native component reference: https://motionary.dev/components - License: https://motionary.dev/license - Machine-readable overview: https://motionary.dev/llms.txt - Machine-readable full catalog: https://motionary.dev/llms-full.txt ## File metadata ``` Canonical URL of this file: https://motionary.dev/animations/apple-weather-rain/llms.txt Describes: https://motionary.dev/animations/apple-weather-rain Format: llms.txt (https://llmstxt.org) Last updated: 2026-09-01 ```