Reanimated徹底解説:React Nativeアニメーションの未来か?


Reanimated徹底解説:React Nativeアニメーションの未来か?

software-mansion/react-native-reanimated

2025-07-28

さあ、今日は「Reanimated」という素晴らしいライブラリについてお話ししましょう!

React Nativeでアニメーションを実装する際に、標準のAnimatedライブラリを使うことが多いですよね。でも、「もっと滑らかに動かないかな…」「UIスレッドがブロックされてカクつく…」なんて感じたことはありませんか?そんな悩みを解決してくれるかもしれないのが、このReanimatedなんです!

でも、このReanimated、実は開発者の間では熱い議論が繰り広げられているんですよ。「信じる派」と「信じない派」に分かれて、まるでコントのように激しい討論が日々行われています。

信じる派リーダー
情熱的なアニメーション愛好家

信じない派リーダー
現実主義のパフォーマンス至上主義者

信じる派リーダー(腕組みをしてニヤリ) 「いやー、Reanimatedは本当に素晴らしい!これを使えば、今まで諦めていたような複雑なアニメーションも、ヌルヌル動くんだよ!UIスレッドに負荷をかけずに、ネイティブ側でアニメーションを処理してくれるんだから、もう最高!」

信じない派リーダー(冷めた目で腕を組み返す) 「ふん、夢ばかり見てるな。確かにパフォーマンスは向上するかもしれない。だが、それだけのために学習コストをかけて、新たなAPIを覚える必要があるのか?既存のAnimatedで十分なケースも多いだろう。それに、デバッグが複雑になる可能性だってあるんだぞ?」

信じる派リーダー(熱弁) 「何を言ってるんだ!その学習コストを払ってでも得られる恩恵は計り知れない!例えば、ジェスチャーとの連携なんて、Reanimatedを使えば驚くほど簡単に、そして滑らかに実現できるんだ!ユーザー体験が格段に向上するんだから、それはもう、投資だよ、投資!」

信じない派リーダー(ため息) 「投資ねぇ…。ちょっとしたアニメーションのためだけに、大掛かりなライブラリを導入するのは、オーバーキルじゃないのか?バンドルサイズも大きくなるし、依存関係が増えることで、将来的なメンテナンスコストだって上がる可能性がある。シンプル・イズ・ベストだろ?」

信じる派リーダー(さらに熱くなる) 「シンプルに見えて、実は複雑なことを裏でやってくれているんだよ!例えば、値の補間やアニメーションの連鎖、ループ処理なども、宣言的に書けるから、コードが分かりやすくなるんだ!それに、Hot Reloadingも強力だし、開発効率だって上がるんだ!」

信じる派リーダー(さらに熱くなる) 「何より、彼らが目指しているのは、React Nativeにおけるアニメーションの究極形なんだ!将来的に、もっと多くの機能が追加され、より簡単に、より高性能なアニメーションが実現できるようになるはずだ!未来に目を向けろ!」

信じない派リーダー(頭を抱える) 「未来はいいが、今をどうするかだ!既存プロジェクトへの導入は?移行コストは?新しいバージョンのたびに、また変更に追われるのか?安定性だって重要だぞ!」

信じる派リーダー(キリッとした表情で) 「大丈夫!公式ドキュメントも充実しているし、コミュニティも活発だ!それに、彼らは常に最高のパフォーマンスと開発体験を提供しようと努力している。信じてみろ!きっと、君のReact Nativeライフが変わるはずだ!」

信じる派リーダー(笑顔で) 「さあ、まずは触ってみることから始めようじゃないか!百聞は一見に如かずだよ!」

信じない派リーダー(渋々ながらも、少し興味を持った様子) 「…まあ、そこまで言うなら、少しは話を聞いてやるか…。」

このコントのように、色々な意見があるReanimatedですが、ソフトウェアエンジニアとしての視点から見ると、以下のような点で非常に役に立ちます。

ネイティブスレッドでのアニメーション実行(UIスレッド解放)
ここが一番のキモです。従来のAnimatedライブラリは、JavaScriptスレッドでアニメーションの計算を行っていました。JavaScriptスレッドはUIのレンダリングやその他のロジックも担当しているため、複雑なアニメーションや頻繁な更新があると、UIスレッドがブロックされてしまい、カクつき(フレーム落ち)が発生することがありました。 Reanimatedは、アニメーションのロジックをネイティブ(C++)側で実行するように最適化されています。これにより、JavaScriptスレッドの負荷が軽減され、UIスレッドがスムーズに動作し、非常に滑らかなアニメーションを実現できます。これは特に、高速なジェスチャー操作や多数の要素が同時に動くようなケースで威力を発揮します。

宣言的なAPIと強力なフック
Reanimatedは、useSharedValue、useAnimatedStyle、useAnimatedGestureHandlerなどのフックを提供しており、これらを使うことで、宣言的にアニメーションを記述できます。これはReactのコンポーネント指向の考え方と非常に相性が良く、コードの可読性と保守性を高めます。

ジェスチャーハンドリングとの連携のしやすさ
react-native-gesture-handlerと組み合わせて使用することで、ユーザーのタッチ操作やスワイプ、ピンチなどのジェスチャーに完璧に同期したアニメーションを簡単に実装できます。例えば、ドラッグ可能な要素や、スワイプで開閉するパネルなど、リッチなUIを少ないコード量で実現可能です。

高度なアニメーション制御
値の補間(interpolate)、アニメーションの連鎖、ループ、条件分岐など、複雑なアニメーションロジックをより直感的に記述できます。また、アニメーションの途中で値を取得したり、イベントを発生させたりすることも可能です。

デバッグのしやすさ(最近は特に向上)
以前はデバッグが難しいという声もありましたが、最近のバージョンでは、デバッグツールが充実してきており、より開発しやすくなっています。

Reanimatedの導入は、いくつかのステップを踏む必要がありますが、公式ドキュメントが非常に丁寧に書かれているので、それに沿って進めれば問題ありません。

まずは、必要なパッケージをインストールします。

yarn add react-native-reanimated react-native-gesture-handler
# または npm install react-native-reanimated react-native-gesture-handler

react-native-gesture-handlerもReanimatedと組み合わせて使うことが多いので、一緒にインストールすることをおすすめします。

babel.config.jsファイルにReanimatedのプラグインを追加します。

module.exports = {
  presets: ['module:@react-native/babel-preset'],
  plugins: [
    'react-native-reanimated/plugin', // この行を追加
  ],
};

重要
'react-native-reanimated/plugin'は、他のプラグイン(特に 'react-native-dotenv' や 'react-native-paper' など)よりも最後に配置する必要があります。これは、プラグインの処理順序が重要だからです。

iOSプロジェクトの場合、Podfileを更新し、Podをインストールする必要があります。

ios/Podfileを開き、一番上に以下の行を追加します。

require_relative '../node_modules/react-native-reanimated/scripts/configure_gradle_for_turbo_modules.rb'

# ... 他のPodfileの内容 ...

次に、ターミナルでiOSディレクトリに移動してPodをインストールします。

cd ios
pod install

App.jsやindex.jsなど、アプリケーションのエントリポイントで、react-native-gesture-handlerのインポートを一番上に追加します。

import 'react-native-gesture-handler'; // この行を一番上に!

import React from 'react';
import { View, Text } from 'react-native';

const App = () => {
  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <Text>Reanimated App</Text>
    </View>
  );
};

export default App;

これで、基本的な導入は完了です。一度アプリを再ビルド(yarn react-native run-ios または yarn react-native run-android)してみてください。

では、実際にReanimatedを使ってシンプルなアニメーションを実装してみましょう。今回は、ボタンをタップすると四角が左右に動くアニメーションと、ドラッグで動かせる四角の例を見てみましょう。

import React from 'react';
import { Button, StyleSheet } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring, // スプリングアニメーション
} from 'react-native-reanimated';

const SIZE = 100;

function BasicMovement() {
  const offset = useSharedValue(0); // アニメーションさせる値を管理するSharedValue

  const animatedStyles = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: offset.value }], // offset.valueに基づいてX座標を変換
    };
  });

  const handlePress = () => {
    offset.value = withSpring(Math.random() * 200 - 100); // ランダムな位置へスプリングアニメーション
  };

  return (
    <>
      <Animated.View style={[styles.box, animatedStyles]} />
      <Button onPress={handlePress} title="動かす!" />
    </>
  );
}

const styles = StyleSheet.create({
  box: {
    width: SIZE,
    height: SIZE,
    backgroundColor: 'hotpink',
    borderRadius: 10,
    marginVertical: 50,
  },
});

export default BasicMovement;

解説

useSharedValue(0)
offsetというShared Valueを初期値0で作成します。これがアニメーションさせる値になります。offset.valueで値にアクセスします。

useAnimatedStyle(() => { ... })
アニメーションされるスタイルを定義するためのフックです。この中の関数はUIスレッドで実行され、offset.valueの変化に応じてスタイルの計算が行われます。

transform: [{ translateX: offset.value }]
offset.valueが変化すると、四角がX軸方向に移動します。

withSpring(Math.random() * 200 - 100)
offset.valueに新しい値を代入する際に、withSpringを使うことで、スプリングアニメーションで滑らかに移動させます。

この例ではreact-native-gesture-handlerも使います。

import React from 'react';
import { StyleSheet } from 'react-native';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  useAnimatedGestureHandler,
  withSpring,
} from 'react-native-reanimated';
import { PanGestureHandler } from 'react-native-gesture-handler';

const SIZE = 100;

function DraggableBox() {
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  // ジェスチャーイベントを処理するハンドラー
  const onGestureEvent = useAnimatedGestureHandler({
    onStart: (event, ctx) => {
      // ジェスチャー開始時の現在の位置を保存
      ctx.startX = translateX.value;
      ctx.startY = translateY.value;
    },
    onActive: (event, ctx) => {
      // 指の移動量に開始時の位置を足して、現在の位置を計算
      translateX.value = ctx.startX + event.translationX;
      translateY.value = ctx.startY + event.translationY;
    },
    onEnd: (event) => {
      // 指を離した時に、初期位置に戻す(例として)
      translateX.value = withSpring(0);
      translateY.value = withSpring(0);
    },
  });

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

  return (
    <PanGestureHandler onGestureEvent={onGestureEvent}>
      <Animated.View style={[styles.box, animatedStyle]} />
    </PanGestureHandler>
  );
}

const styles = StyleSheet.create({
  box: {
    width: SIZE,
    height: SIZE,
    backgroundColor: 'purple',
    borderRadius: 10,
    marginTop: 50, // 上からの余白
  },
});

export default DraggableBox;

解説

PanGestureHandler
react-native-gesture-handlerから提供されるコンポーネントで、パン(ドラッグ)ジェスチャーを検出します。

useAnimatedGestureHandler({ ... })
ジェスチャーイベント(onStart、onActive、onEndなど)が発生した際に実行されるロジックを定義します。この中もUIスレッドで実行されます。

ctx
contextオブジェクトで、ジェスチャーの開始時などの状態を保持するために使えます。

event.translationX, event.translationY
指がどれだけ移動したか(翻訳量)を示します。

onEnd
ジェスチャーが終了した際に、スプリングアニメーションで初期位置(0, 0)に戻るようにしています。

Reanimatedは、React Nativeでより高度で滑らかなアニメーションを実装するための強力なツールです。確かに学習コストや導入の手間はありますが、その恩恵は大きく、特にパフォーマンスが重視されるアプリケーションや、リッチなUIアニメーションを必要とする場合に、その真価を発揮します。

「信じる派」の意見のように、未来のReact Nativeアニメーションを担う可能性を秘めたライブラリだと私は思います。まずは触ってみて、そのスムーズさを体験してみてください!きっと、「信じる派」の気持ちが少しは理解できるはずです!


software-mansion/react-native-reanimated




ReactでiOS/Androidアプリを同時開発!Expoの基本とサンプルコードを彼女との会話で解説

彼女がそう言って、キラキラした目で試着室から出てきました。 「うーん、似合うと思うよ。でもさ、それってさっき見てたのとちょっと違うデザインじゃない?」僕がスマホをいじりながら返事をすると、彼女は少し頬を膨らませました。 「もう!ちゃんと見てる?今日、デートだって言ったでしょ?」


彼女のランジェリー選びとESLintのコント

彼女のランジェリー選び、さながら複雑なJavaScriptのコードですね! どれも魅力的に見えるけど、サイズが合わなかったり、着心地が悪かったり、合わせる服が難しかったり…。ESLintは、そんな彼女の悩みを解決するあなたの最高のパートナーです。 彼女が素敵なランジェリーを選べるよう、あなたはESLintを使って、プロの視点からアドバイスをしてあげられます。


名探偵の技術解析:巨大リポジトリ「mdn/content」を解析してWeb標準のプロになる

おっと、失礼。名探偵の助手くん、君もこの『mdn/content』という謎に包まれたリポジトリの正体が気になりますか?世界中のエンジニアが毎日お世話になっている「MDN Web Docs」の心臓部。これをエンジニアが「読み物」としてではなく「ツール」として使いこなすとどうなるか……。私の推理を聞いていただけますか?


Motiaの魔法の杖で開発の悩みを解決!API、ワークフロー、AIを統合する現代のバックエンドフレームワーク

今回は、すごい魔法アイテムを紹介するよ!その名も「MotiaDev/motia」!まるで、魔法少女の変身アイテムみたいに、あなたの開発を華やかに彩ってくれる、素敵な魔法の杖なんだ。昔々、あるところに、たくさんの魔法使いが住んでいました。彼らは、それぞれ得意な魔法を持っていました。


Web技術とネイティブアプリの融合:WebKit入門

WebKitは、Appleが開発したWebブラウザのレンダリングエンジンです。簡単に言うと、Webページを画面に表示するための、ブラウザの心臓部にあたるソフトウェアですね。みなさんが普段使っているSafariや、iPhone/iPadのアプリ内でWebページを表示する機能は、すべてこのWebKitが動かしています。


ソフトウェアエンジニア必見! MCPでAI開発の密室を突破する

おいおい、一体どういうことだ!? この部屋は完全に密室じゃないか!…おっと、すみません。ついドラマの役に入り込んでしまいました。でも、この密室、実は我々ソフトウェアエンジニアの目の前にある「AI開発の密室」かもしれません。「ん? AIの密室ってどういうこと?」と、あなたは首を傾げていますね。ご説明しましょう。


サヨナラ属人化!Markdown対応知識ベースで爆速開発チームへ変貌

「うおおおお!またこのバグ!?」「え、この仕様どこに書いてあるの…?」「前に誰か解決してた気がするんだけどな…」皆さん、よくある光景ですよね?炎上プロジェクトでは、情報が散乱し、ナレッジが共有されず、同じような問題に何度もぶつかることが日常茶飯事です。そんなカオスを打開し、チームを救う切り札となるのが、今回ご紹介する「爆速知識ベース」です!


Webエンジニア必見!ytDownloaderから学ぶ「動画解析とデータ処理」の実用的なアプローチ

恋がそうであるように、このツールとの出会いも、あなたのエンジニアライフを豊かにする可能性がありますよ!この「aandrew-me/ytDownloader」は、単なるダウンローダーというだけでなく、「Electron」「Node. js」「JavaScript」という、現代のフロントエンド・バックエンド技術を組み合わせた「デスクトップアプリケーション開発」の教材であり、ソリューションの塊です。


「情報を探す時間」を消滅させるAIパートナー:MineContextの技術スタック(PythonによるRAGとElectron/ReactによるUX)

「落ち着け、相棒!見ろ、このキーワードだ. ..volcengine/MineContext、electron、react、python. ..そして『コンテキストアウェアなAIパートナー』だと!?これはただの事件じゃない、ソフトウェア開発における『生産性の殺人事件』だ!」


ガシャポン攻略法:TanStack RouterでReactのルーティングを制覇する

TanStack Routerは、Reactアプリケーションでルーティングを管理するための、強力で型安全なライブラリです。単にページを切り替えるだけでなく、もっと複雑な要件にも対応できる、まさに「ガシャポンの攻略法」のようなライブラリです。