jpskill.com
🎨 デザイン コミュニティ

reanimated-skia-performance

Write and review high-performance React Native animations and 2D graphics using react-native-reanimated (v4+) and @shopify/react-native-skia (Canvas scenes, runtime effects/shaders). Use for: gesture-driven interactions, spring/timing transitions, layout/mount animations, Reanimated CSS transitions/animations, Skia drawings, animated shader uniforms, path/vector interpolation, dev-mode tuning panels (sliders), and diagnosing animation jank (JS thread stalls, excessive re-renders, per-frame allocations).

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

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

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

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

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して reanimated-skia-performance.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → reanimated-skia-performance フォルダができる
  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
同梱ファイル
5

📖 Skill本文(日本語訳)

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

Reanimated + Skia のパフォーマンス

デフォルト

  • アニメーションの状態は UI スレッドに保持します: useSharedValueuseDerivedValue、ワークレット。
  • Reanimated v4 の宣言型 API を優先し、レガシーな Animated は避けます。
  • アプリケーションコードでは shared.value よりも shared.get() / shared.set() を優先します (React Compiler との親和性が高いです)。
  • JS↔UI 間のやり取りを最小限に抑えます: 避けられない副作用を除き、scheduleOnRN/runOnJS は使用しません。
  • Skia の場合、フレームごとの React レンダリングを避けます: SharedValue を Skia の props/uniforms に直接渡します。

ワークフロー

  1. エフェクトを定義します: 何をアニメーションさせるか、期間/カーブ、中断ルール、ジェスチャー入力。
  2. レンダラーを選択します:
    • 変形/不透明度/レイアウトには Reanimated のスタイルを使用します。
    • カスタム描画、パーティクル、グラデーション、ランタイムエフェクト/シェーダーには Skia を使用します。
  3. プリミティブを選択します:
    • シンプルな宣言型スタイル変更には Reanimated の CSS トランジション/アニメーションを使用します。
    • トゥイーンには withTiming、物理演算には withSpring、慣性には withDecay を使用します。
    • マウント/アンマウントまたはレイアウト変更にはレイアウトアニメーションを使用します。
  4. UI スレッドで単一のデータフローを実装します (フレームごとの setState は使用しません)。
  5. パフォーマンスチェックを行います (references/perf-checklist.md を参照してください)。

パターン

共有値 (React Compiler セーフ)

  • 読み取り: progress.get()
  • 書き込み: progress.set(withTiming(1))
import { useEffect } from 'react';
import { useSharedValue, withTiming } from 'react-native-reanimated';

const progress = useSharedValue(0);

useEffect(() => {
  progress.set(withTiming(1, { duration: 400 }));
}, [progress]);

Reanimated v4 CSS トランジション

独自のワークレットを必要としない、状態駆動型のスタイル変更に使用します。

import Animated from 'react-native-reanimated';

<Animated.View
  style={{
    width: expanded ? 240 : 160,
    opacity: enabled ? 1 : 0.6,
    transitionProperty: ['width', 'opacity'],
    transitionDuration: 220,
    transitionTimingFunction: 'ease-in-out',
  }}
/>

Reanimated v4 CSS アニメーション (キーフレーム)

カスタムワークレットを書かずに、キーフレームのようなシーケンス (パルス、揺れ、繰り返しループ) に使用します。

サポートされている設定:

  • animationName (キーフレームオブジェクト)
  • animationDuration
  • animationDelay
  • animationTimingFunction
  • animationDirection
  • animationIterationCount
  • animationFillMode
  • animationPlayState
import Animated from 'react-native-reanimated';

const pulse = {
  from: { transform: [{ scale: 1 }], opacity: 0.9 },
  '50%': { transform: [{ scale: 1.06 }], opacity: 1 },
  to: { transform: [{ scale: 1 }], opacity: 0.9 },
};

<Animated.View
  style={{
    animationName: pulse,
    animationDuration: '900ms',
    animationDelay: '80ms',
    animationTimingFunction: 'ease-in-out',
    animationDirection: 'alternate',
    animationIterationCount: 'infinite',
    animationFillMode: 'both',
    animationPlayState: paused ? 'paused' : 'running',
  }}
/>

開発モードチューニングパネル (スライダー)

__DEV__ モードでスライダーを使用して、アニメーション設定やシェーダーの uniform を調整します。

  • アニメーションシーンの再レンダリングを避けるため、チューニング UI は別のコンポーネントに保持します。
  • スライダーの値を .set() を介して SharedValue に書き込みます。
  • シェーダーのチューニングの場合: useDerivedValue を介して SharedValue を uniform に供給します。
  • アニメーション設定のチューニングの場合: 設定パラメータを SharedValue に格納し、アニメーションの開始/再開時にそれらを読み取ります。

参照: references/dev-tuning.md

ジェスチャー駆動アニメーション (Gesture Builder API)

onUpdate で共有値を更新し、アニメーションスタイルを介してビジュアルを駆動します。

import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';

const x = useSharedValue(0);
const gesture = Gesture.Pan()
  .onUpdate((e) => {
    x.set(e.translationX);
  })
  .onEnd(() => {
    x.set(withSpring(0));
  });

const style = useAnimatedStyle(() => ({ transform: [{ translateX: x.get() }] }));

<GestureDetector gesture={gesture}>
  <Animated.View style={style} />
</GestureDetector>;

アニメーションする uniform を持つ Skia シェーダー

  • ランタイムエフェクトは一度だけコンパイルします (useMemo)。
  • uniform を SharedValue<Uniforms> として渡します (Skia は { value: T } によってアニメーションする props を検出します)。
  • アプリケーションコードで .value にアクセスせず、SharedValue オブジェクトを渡します。
import { useMemo } from 'react';
import { Skia, Canvas, Fill, Paint, Shader, type Uniforms } from '@shopify/react-native-skia';
import { useDerivedValue } from 'react-native-reanimated';
import { useClock } from '@shopify/react-native-skia';

const sksl = `
uniform float2 u_resolution;
uniform float u_time;

half4 main(float2 xy) {
  float2 uv = xy / u_resolution;
  float v = 0.5 + 0.5 * sin(u_time * 0.002 + uv.x * 8.0);
  return half4(v, v * 0.6, 1.0 - v, 1.0);
}
`;

const effect = useMemo(() => Skia.RuntimeEffect.Make(sksl), []);
if (!effect) return null;

const clock = useClock(); // 最初のフレームからのミリ秒
const uniforms = useDerivedValue<Uniforms>(() => ({
  u_resolution: Skia.Point(width, height),
  u_time: clock.get(),
}));

<Canvas style={{ width, height }}>
  <Fill>
    <Paint>
      <Shader source={effect} uniforms={uniforms} />
    </Paint>
  </Fill>
</Canvas>;

よくある落とし穴

  • React のレンダー内で共有値を読み取らないでください。ワークレット (useAnimatedStyleuseDerivedValue) で読み取ります。
  • 必須の場合を除き、onUpdaterunOnJS/scheduleOnRN を呼び出さないでください。
  • フレームごとに大きな配列/パス/画像を割り当てないでください。Skia オブジェクトをメモ化し、アニメーションする props を介して更新します。
  • ランタイムエフェクトの場合、シェーダーで宣言されたすべての uniform を常に提供してください。uniform が不足しているとエラーが発生します。

参照

  • Reanimated v4 のパターンとリポジトリの慣例: references/reanimated-v4.md
  • Skia Canvas + ランタイムエフェクト/シェーダーのパターン: references/skia-shaders.md
  • 開発モードチューニングパネル (スライダー): references/dev-tuning.md
  • パフォーマンスチェックリスト + デバッグ: references/perf-checklist.md
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Reanimated + Skia Performance

Defaults

  • Keep animation state on the UI thread: useSharedValue, useDerivedValue, worklets.
  • Prefer Reanimated v4 declarative APIs; avoid legacy Animated.
  • Prefer shared.get() / shared.set() over shared.value in app code (React Compiler friendly).
  • Minimize JS↔UI crossings: avoid scheduleOnRN/runOnJS except for unavoidable side effects.
  • For Skia, avoid per-frame React renders: pass SharedValues directly to Skia props/uniforms.

Workflow

  1. Define the effect: what animates, duration/curve, interrupt rules, and gesture input.
  2. Choose the renderer:
    • Use Reanimated styles for transforms/opacity/layout.
    • Use Skia for custom drawing, particles, gradients, runtime effects/shaders.
  3. Choose the primitive:
    • Use Reanimated CSS transitions/animations for simple declarative style changes.
    • Use withTiming for tweens, withSpring for physics, withDecay for momentum.
    • Use Layout Animations for mount/unmount or layout changes.
  4. Implement a single data flow on the UI thread (no setState per frame).
  5. Do a perf pass (see references/perf-checklist.md).

Patterns

Shared values (React Compiler safe)

  • Read: progress.get()
  • Write: progress.set(withTiming(1))
import { useEffect } from 'react';
import { useSharedValue, withTiming } from 'react-native-reanimated';

const progress = useSharedValue(0);

useEffect(() => {
  progress.set(withTiming(1, { duration: 400 }));
}, [progress]);

Reanimated v4 CSS transitions

Use for state-driven style changes where you do not need bespoke worklets.

import Animated from 'react-native-reanimated';

<Animated.View
  style={{
    width: expanded ? 240 : 160,
    opacity: enabled ? 1 : 0.6,
    transitionProperty: ['width', 'opacity'],
    transitionDuration: 220,
    transitionTimingFunction: 'ease-in-out',
  }}
/>

Reanimated v4 CSS animations (keyframes)

Use for keyframe-like sequences (pulses, wiggles, repeated loops) without writing custom worklets.

Supported settings:

  • animationName (keyframes object)
  • animationDuration
  • animationDelay
  • animationTimingFunction
  • animationDirection
  • animationIterationCount
  • animationFillMode
  • animationPlayState
import Animated from 'react-native-reanimated';

const pulse = {
  from: { transform: [{ scale: 1 }], opacity: 0.9 },
  '50%': { transform: [{ scale: 1.06 }], opacity: 1 },
  to: { transform: [{ scale: 1 }], opacity: 0.9 },
};

<Animated.View
  style={{
    animationName: pulse,
    animationDuration: '900ms',
    animationDelay: '80ms',
    animationTimingFunction: 'ease-in-out',
    animationDirection: 'alternate',
    animationIterationCount: 'infinite',
    animationFillMode: 'both',
    animationPlayState: paused ? 'paused' : 'running',
  }}
/>

Dev-mode tuning panel (sliders)

Use sliders to tune animation configs or shader uniforms in __DEV__.

  • Keep the tuning UI in a separate component to avoid re-rendering the animated scene.
  • Write slider values into SharedValues via .set().
  • For shader tuning: feed SharedValues into uniforms via useDerivedValue.
  • For animation config tuning: store config params in SharedValues and read them when starting/restarting the animation.

See: references/dev-tuning.md.

Gesture-driven animation (Gesture Builder API)

Update shared values in onUpdate and drive visuals via animated styles.

import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated';

const x = useSharedValue(0);
const gesture = Gesture.Pan()
  .onUpdate((e) => {
    x.set(e.translationX);
  })
  .onEnd(() => {
    x.set(withSpring(0));
  });

const style = useAnimatedStyle(() => ({ transform: [{ translateX: x.get() }] }));

<GestureDetector gesture={gesture}>
  <Animated.View style={style} />
</GestureDetector>;

Skia shader with animated uniforms

  • Compile the runtime effect once (useMemo).
  • Pass uniforms as a SharedValue<Uniforms> (Skia detects animated props by { value: T }).
  • Do not access .value in your app code; pass the SharedValue object.
import { useMemo } from 'react';
import { Skia, Canvas, Fill, Paint, Shader, type Uniforms } from '@shopify/react-native-skia';
import { useDerivedValue } from 'react-native-reanimated';
import { useClock } from '@shopify/react-native-skia';

const sksl = `
uniform float2 u_resolution;
uniform float u_time;

half4 main(float2 xy) {
  float2 uv = xy / u_resolution;
  float v = 0.5 + 0.5 * sin(u_time * 0.002 + uv.x * 8.0);
  return half4(v, v * 0.6, 1.0 - v, 1.0);
}
`;

const effect = useMemo(() => Skia.RuntimeEffect.Make(sksl), []);
if (!effect) return null;

const clock = useClock(); // ms since first frame
const uniforms = useDerivedValue<Uniforms>(() => ({
  u_resolution: Skia.Point(width, height),
  u_time: clock.get(),
}));

<Canvas style={{ width, height }}>
  <Fill>
    <Paint>
      <Shader source={effect} uniforms={uniforms} />
    </Paint>
  </Fill>
</Canvas>;

Common pitfalls

  • Do not read shared values in React render; read them in worklets (useAnimatedStyle, useDerivedValue).
  • Do not call runOnJS/scheduleOnRN in onUpdate unless you must.
  • Do not allocate big arrays/paths/images per frame; memoize Skia objects and update via animated props.
  • For runtime effects, always provide every uniform declared in the shader; missing uniforms throw.

References

  • Reanimated v4 patterns and repo conventions: references/reanimated-v4.md
  • Skia Canvas + runtime effects/shaders patterns: references/skia-shaders.md
  • Dev-mode tuning panels (sliders): references/dev-tuning.md
  • Performance checklist + debugging: references/perf-checklist.md

同梱ファイル

※ ZIPに含まれるファイル一覧。`SKILL.md` 本体に加え、参考資料・サンプル・スクリプトが入っている場合があります。