jpskill.com
🛠️ 開発・MCP コミュニティ

react-native-reanimated

React Nativeで滑らかな60fpsのアニメーションを実現し、UIスレッド上で動作させることでJSブリッジの遅延をなくし、ジェスチャーやスクロールに連動した高度なアニメーションを実装するSkill。

📜 元の英語説明(参考)

Build smooth 60fps animations in React Native with Reanimated — run animations on the UI thread without JS bridge delays. Use when someone asks to "animate in React Native", "Reanimated", "smooth mobile animations", "gesture animations", "shared element transitions", or "60fps React Native animations". Covers worklets, shared values, layout animations, gestures, and scroll-driven animations.

🇯🇵 日本人クリエイター向け解説

一言でいうと

React Nativeで滑らかな60fpsのアニメーションを実現し、UIスレッド上で動作させることでJSブリッジの遅延をなくし、ジェスチャーやスクロールに連動した高度なアニメーションを実装するSkill。

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o react-native-reanimated.zip https://jpskill.com/download/15322.zip && unzip -o react-native-reanimated.zip && rm react-native-reanimated.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15322.zip -OutFile "$d\react-native-reanimated.zip"; Expand-Archive "$d\react-native-reanimated.zip" -DestinationPath $d -Force; ri "$d\react-native-reanimated.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して react-native-reanimated.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → react-native-reanimated フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

React Native Reanimated

概要

Reanimated は、ネイティブ UI スレッド上でアニメーションを実行します。JS ブリッジのボトルネックがなく、フレーム落ちもありません。JavaScript スレッドがビジーな状態でも、アニメーションは 60fps を維持します。「worklet」と呼ばれる、JSI を介して UI スレッド上で実行される小さな JavaScript 関数を使用します。React Native におけるプロダクション品質のアニメーションの標準であり、ジェスチャー駆動のインタラクション、レイアウトトランジション、スクロールベースのエフェクト、共有要素トランジションを実現します。

どのような時に使うか

  • React Native における単純な opacity/transform を超えるあらゆるアニメーション
  • ジェスチャー駆動のインタラクション (スワイプして削除、ドラッグして並べ替え、ピンチしてズーム)
  • スクロール駆動のアニメーション (パララックスヘッダー、スティッキー要素)
  • レイアウトアニメーション (リストへのアイテムの出入り)
  • 画面間の共有要素トランジション

手順

セットアップ

npx expo install react-native-reanimated react-native-gesture-handler
// babel.config.js — Reanimated プラグインを追加 (必ず最後に)
module.exports = function (api) {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
    plugins: ["react-native-reanimated/plugin"],  // Must be last!
  };
};

共有値とアニメーションスタイル

// components/FadeIn.tsx — 共有値を使った基本的なアニメーション
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withTiming,
  withSpring,
} from "react-native-reanimated";
import { useEffect } from "react";

export function FadeInCard({ children }) {
  const opacity = useSharedValue(0);
  const translateY = useSharedValue(20);

  useEffect(() => {
    opacity.value = withTiming(1, { duration: 600 });
    translateY.value = withSpring(0, { damping: 15 });
  }, []);

  const animatedStyle = useAnimatedStyle(() => ({
    opacity: opacity.value,
    transform: [{ translateY: translateY.value }],
  }));

  return (
    <Animated.View style={animatedStyle} className="bg-white rounded-xl p-4 shadow-lg">
      {children}
    </Animated.View>
  );
}

ジェスチャーアニメーション

// components/SwipeToDelete.tsx — アニメーション付きのスワイプジェスチャー
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  runOnJS,
} from "react-native-reanimated";
import { Gesture, GestureDetector } from "react-native-gesture-handler";

export function SwipeToDelete({ onDelete, children }) {
  const translateX = useSharedValue(0);

  const pan = Gesture.Pan()
    .onUpdate((event) => {
      // 左スワイプのみ許可
      translateX.value = Math.min(0, event.translationX);
    })
    .onEnd((event) => {
      if (event.translationX < -150) {
        // 十分にスワイプ — 削除
        translateX.value = withSpring(-400);
        runOnJS(onDelete)();
      } else {
        // スナップバック
        translateX.value = withSpring(0);
      }
    });

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: translateX.value }],
  }));

  return (
    <GestureDetector gesture={pan}>
      <Animated.View style={animatedStyle}>
        {children}
      </Animated.View>
    </GestureDetector>
  );
}

レイアウトアニメーション

// components/AnimatedList.tsx — アイテムが自動的にアニメーションイン/アウト
import Animated, { FadeInDown, FadeOutLeft, LinearTransition } from "react-native-reanimated";

export function AnimatedList({ items, onRemove }) {
  return (
    <Animated.FlatList
      data={items}
      itemLayoutAnimation={LinearTransition}
      renderItem={({ item, index }) => (
        <Animated.View
          entering={FadeInDown.delay(index * 100).springify()}
          exiting={FadeOutLeft.duration(300)}
          className="bg-white p-4 mx-4 my-1 rounded-lg"
        >
          <Text>{item.title}</Text>
          <Pressable onPress={() => onRemove(item.id)}>
            <Text className="text-red-500">Remove</Text>
          </Pressable>
        </Animated.View>
      )}
    />
  );
}

スクロール駆動のアニメーション

// components/ParallaxHeader.tsx — スクロール時のパララックス効果
import Animated, {
  useAnimatedScrollHandler,
  useSharedValue,
  useAnimatedStyle,
  interpolate,
} from "react-native-reanimated";

export function ParallaxHeader() {
  const scrollY = useSharedValue(0);

  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (event) => {
      scrollY.value = event.contentOffset.y;
    },
  });

  const headerStyle = useAnimatedStyle(() => ({
    height: interpolate(scrollY.value, [-100, 0, 200], [400, 300, 100]),
    opacity: interpolate(scrollY.value, [0, 200], [1, 0.3]),
    transform: [
      { translateY: interpolate(scrollY.value, [0, 200], [0, -50]) },
    ],
  }));

  return (
    <>
      <Animated.View style={headerStyle} className="bg-blue-600">
        <Text className="text-white text-3xl font-bold">My App</Text>
      </Animated.View>
      <Animated.ScrollView onScroll={scrollHandler} scrollEventThrottle={16}>
        {/* Content */}
      </Animated.ScrollView>
    </>
  );
}

例 1: カードスワイプインターフェースを構築する

ユーザープロンプト: 「スムーズなアニメーションで Tinder スタイルのカードスワイプインターフェースを構築してください。」

エージェントは、パンジェスチャー、スワイプ方向に基づく回転、スナップバックのためのスプリングアニメーション、およびカード削除のためのレイアウトトランジションを備えたカードスタックを作成します。

例 2: アニメーション付きボトムシート

ユーザープロンプト: 「ドラッグして位置にスナップできるボトムシートを作成してください。」

エージェントは、スナップポイント付きのパンジェスチャー、高さの共有値、およびスムーズなスナップのためのスプリングアニメーションを使用します。

ガイドライン

  • アニメーション状態のための共有値useSharedValue は UI スレッドで実行されます
  • 動的なスタイルのための useAnimatedStyle — UI スレッドで再計算されます
  • 自然な動きのための withSpring — 正確な期間のための withTiming
  • worklet から JS を呼び出すための runOnJS — 必要に応じて JS スレッドにブリッジバックします
  • Gesture Handler の統合Gesture.Pan()Gesture.Pinch() など
  • レイアウトアニメーションは宣言的 — Animated コンポーネントの enteringexiting プロパティ
  • 値のマッピングのための interpolate — スクロール位置をマッピングします

(原文がここで切り詰められています)

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

React Native Reanimated

Overview

Reanimated runs animations on the native UI thread — no JS bridge bottleneck, no dropped frames. Animations stay at 60fps even when your JavaScript thread is busy. It uses "worklets" — small JavaScript functions that execute on the UI thread via JSI. The standard for production-quality animations in React Native: gesture-driven interactions, layout transitions, scroll-based effects, and shared element transitions.

When to Use

  • Any animation in React Native beyond simple opacity/transform
  • Gesture-driven interactions (swipe to delete, drag to reorder, pinch to zoom)
  • Scroll-driven animations (parallax headers, sticky elements)
  • Layout animations (items entering/leaving lists)
  • Shared element transitions between screens

Instructions

Setup

npx expo install react-native-reanimated react-native-gesture-handler
// babel.config.js — Add the Reanimated plugin (MUST be last)
module.exports = function (api) {
  api.cache(true);
  return {
    presets: ["babel-preset-expo"],
    plugins: ["react-native-reanimated/plugin"],  // Must be last!
  };
};

Shared Values and Animated Styles

// components/FadeIn.tsx — Basic animation with shared values
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withTiming,
  withSpring,
} from "react-native-reanimated";
import { useEffect } from "react";

export function FadeInCard({ children }) {
  const opacity = useSharedValue(0);
  const translateY = useSharedValue(20);

  useEffect(() => {
    opacity.value = withTiming(1, { duration: 600 });
    translateY.value = withSpring(0, { damping: 15 });
  }, []);

  const animatedStyle = useAnimatedStyle(() => ({
    opacity: opacity.value,
    transform: [{ translateY: translateY.value }],
  }));

  return (
    <Animated.View style={animatedStyle} className="bg-white rounded-xl p-4 shadow-lg">
      {children}
    </Animated.View>
  );
}

Gesture Animations

// components/SwipeToDelete.tsx — Swipe gesture with animation
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  runOnJS,
} from "react-native-reanimated";
import { Gesture, GestureDetector } from "react-native-gesture-handler";

export function SwipeToDelete({ onDelete, children }) {
  const translateX = useSharedValue(0);

  const pan = Gesture.Pan()
    .onUpdate((event) => {
      // Only allow left swipe
      translateX.value = Math.min(0, event.translationX);
    })
    .onEnd((event) => {
      if (event.translationX < -150) {
        // Swipe far enough — delete
        translateX.value = withSpring(-400);
        runOnJS(onDelete)();
      } else {
        // Snap back
        translateX.value = withSpring(0);
      }
    });

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ translateX: translateX.value }],
  }));

  return (
    <GestureDetector gesture={pan}>
      <Animated.View style={animatedStyle}>
        {children}
      </Animated.View>
    </GestureDetector>
  );
}

Layout Animations

// components/AnimatedList.tsx — Items animate in/out automatically
import Animated, { FadeInDown, FadeOutLeft, LinearTransition } from "react-native-reanimated";

export function AnimatedList({ items, onRemove }) {
  return (
    <Animated.FlatList
      data={items}
      itemLayoutAnimation={LinearTransition}
      renderItem={({ item, index }) => (
        <Animated.View
          entering={FadeInDown.delay(index * 100).springify()}
          exiting={FadeOutLeft.duration(300)}
          className="bg-white p-4 mx-4 my-1 rounded-lg"
        >
          <Text>{item.title}</Text>
          <Pressable onPress={() => onRemove(item.id)}>
            <Text className="text-red-500">Remove</Text>
          </Pressable>
        </Animated.View>
      )}
    />
  );
}

Scroll-Driven Animations

// components/ParallaxHeader.tsx — Parallax effect on scroll
import Animated, {
  useAnimatedScrollHandler,
  useSharedValue,
  useAnimatedStyle,
  interpolate,
} from "react-native-reanimated";

export function ParallaxHeader() {
  const scrollY = useSharedValue(0);

  const scrollHandler = useAnimatedScrollHandler({
    onScroll: (event) => {
      scrollY.value = event.contentOffset.y;
    },
  });

  const headerStyle = useAnimatedStyle(() => ({
    height: interpolate(scrollY.value, [-100, 0, 200], [400, 300, 100]),
    opacity: interpolate(scrollY.value, [0, 200], [1, 0.3]),
    transform: [
      { translateY: interpolate(scrollY.value, [0, 200], [0, -50]) },
    ],
  }));

  return (
    <>
      <Animated.View style={headerStyle} className="bg-blue-600">
        <Text className="text-white text-3xl font-bold">My App</Text>
      </Animated.View>
      <Animated.ScrollView onScroll={scrollHandler} scrollEventThrottle={16}>
        {/* Content */}
      </Animated.ScrollView>
    </>
  );
}

Examples

Example 1: Build a card swipe interface

User prompt: "Build a Tinder-style card swipe interface with smooth animations."

The agent will create a card stack with pan gestures, rotation based on swipe direction, spring animations for snap-back, and layout transitions for card removal.

Example 2: Animated bottom sheet

User prompt: "Create a bottom sheet that can be dragged up and snaps to positions."

The agent will use pan gestures with snap points, shared values for height, and spring animations for smooth snapping.

Guidelines

  • Shared values for animation stateuseSharedValue runs on UI thread
  • useAnimatedStyle for dynamic styles — recalculated on UI thread
  • withSpring for natural motionwithTiming for precise duration
  • runOnJS to call JS from worklets — bridge back to JS thread when needed
  • Gesture Handler integrationGesture.Pan(), Gesture.Pinch(), etc.
  • Layout animations are declarativeentering, exiting props on Animated components
  • interpolate for value mapping — map scroll position to opacity, scale, etc.
  • Babel plugin must be lastreact-native-reanimated/plugin at end of plugins array
  • Don't access JS objects in worklets — only shared values and primitives
  • scrollEventThrottle={16} — 60fps scroll events for smooth animations