Skip to content
Native Animation
Scratch Card Reveal animation preview

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

npx nativeanimation add scratch-card-reveal
Skia

Scratch Card Reveal

A scratch card with coverage-based reward reveal and configurable reward copy, labels, metallic colors, and fonts.

$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 scratch card with coverage-based reward reveal and configurable reward copy, labels, metallic colors, and fonts.

How it works

  1. A Skia layer builds brushed copper from a three-stop gradient, fine grain, and a moving specular highlight.
  2. A Gesture Handler pan appends points to a soft 34-point clear stroke inside a saved Skia layer.
  3. The gesture marks a 12 × 8 coverage grid instead of reading pixels, keeping the reveal deterministic and inexpensive.
  4. One shared reveal progress drives the remaining metal dissolve, reward lift, confetti burst, and wallet action.
  5. The imperative play() method traces a measured zigzag for autoplay demos; reveal() provides a tap-accessible alternative.

Install

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

For web, initialize CanvasKit before rendering the component and make the CanvasKit WASM asset available to your bundler. Wrap your app root with GestureHandlerRootView on every platform.

Icons: Lucide (ISC).

Usage

import { ScratchCardReveal } from './ScratchCardReveal';

export function Reward() {
  return (
    <ScratchCardReveal
      rewardTitle="Coffee on us"
      rewardDetail="Any size · Valid through 10/31"
      rewardCode="REWARD-24"
      onAddToWallet={() => saveReward()}
    />
  );
}

With personality knobs and imperative control:

const card = useRef<ScratchCardRevealRef>(null);

<ScratchCardReveal
  ref={card}
  accentColor="#B8552F"
  metalColors={['#E8C07A', '#B7793C', '#F3D49B']}
  scratchWidth={36}
  cardWidthRatio={0.88}
  onReveal={() => announceReward()}
/>;

card.current?.play();

Props

PropTypeDefaultDescription
eyebrowstring'FREE'Short reward category.
rewardTitlestring'Your favorite drink'Main reward name.
rewardDetailstring'Any size · Valid through 10/31'Validity or offer detail.
rewardCodestring'REWARD-24'Redemption code.
scratchLabelstring'Scratch here'Engraved instruction.
walletLabelstring'Add to wallet'Wallet action label.
replayLabelstring'Replay'Reset action label.
cardWidthRationumber0.84Card width relative to the component.
cornerRadiusnumber24Card corner radius.
scratchWidthnumber34Scratch stroke width.
rewardColorstring'#FFF6E8'Reward surface color.
metalColors[string, string, string]copper paletteBrushed metal gradient.
accentColorstring'#B8552F'Reward and action accent.
fontFamilystringsystemInterface font family.
mediumFontFamilystringsystemEmphasized interface font family.
titleFontFamilystringsystemEditorial reward font family.
monoFontFamilystringsystemRedemption code font family.
onReveal() => void—Called once per reveal.
onAddToWallet() => void—Called by the wallet action.
accessibilityLabelstring'Reveal reward'Scratch surface label.
styleStyleProp<ViewStyle>—Outer container style.
testIDstring—Outer container test identifier.

The forwarded ref exposes play(), reveal(), and reset().

Compatibility

  • Expo SDK 58
  • React Native 0.88.0
  • Reanimated 4.7.1 and Worklets 0.13.0
  • React Native Skia 2.14.0
  • iOS: supported
  • Android: supported
  • Web: supported
  • Expo Go: supported because every native dependency is included in Expo Go for SDK 58

Accessibility

The scratch surface exposes a button role and an activate action, so a screen reader can reveal the prize without drawing. All controls meet the 44-point target minimum. Reduced Motion replaces the zigzag, lift, and particle travel with a short fade.

Why this one

Most scratch cards stop at a flat gray mask. This version couples measured grid coverage with a layered copper material, soft-edged removal, physical crumbs, a compact product-ready API, and a coordinated reward celebration—all without reading pixels or updating React state on every gesture frame.

Customization notes

Movement follows gestures, scroll position, or interruptible spring physics. A global duration is not exposed; reduced-motion fades retain their short fixed timing.