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本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
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
$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. 下の青いボタンを押して
react-native-reanimated.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
react-native-reanimatedフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
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 コンポーネントの
entering、exitingプロパティ - 値のマッピングのための
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 state —
useSharedValueruns on UI thread useAnimatedStylefor dynamic styles — recalculated on UI threadwithSpringfor natural motion —withTimingfor precise durationrunOnJSto call JS from worklets — bridge back to JS thread when needed- Gesture Handler integration —
Gesture.Pan(),Gesture.Pinch(), etc. - Layout animations are declarative —
entering,exitingprops on Animated components interpolatefor value mapping — map scroll position to opacity, scale, etc.- Babel plugin must be last —
react-native-reanimated/pluginat end of plugins array - Don't access JS objects in worklets — only shared values and primitives
scrollEventThrottle={16}— 60fps scroll events for smooth animations