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は、useSharedValueuseAnimatedStyleuseAnimatedGestureHandlerなどのフックを提供しており、これらを使うことで、宣言的にアニメーションを記述できます。これは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.jsindex.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({ ... })
ジェスチャーイベント(onStartonActiveonEndなど)が発生した際に実行されるロジックを定義します。この中もUIスレッドで実行されます。

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

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

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

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

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


software-mansion/react-native-reanimated




ふらっと立ち寄った居酒屋で聞く、Prisma入門

「Prisma」ってのはよ、まぁ、あの、えーと… 「データベースと仲良くなるためのすごいヤツ」 だな!いや、もっとちゃんと話すと、「次世代のORM(Object-Relational Mapper)」 ってやつだよ。ORMってのは、データベースのテーブルとかを、JavaScriptとかのプログラムで扱うオブジェクト(クラスとか)にしてくれる魔法の道具って思ってくれや。


ドラッグ&ドロップで設計!ノードベースUI構築ライブラリ「React Flow / Svelte Flow」入門と活用事例

お悩みはさておき、ご質問のxyflow/xyflowについて、ソフトウェアエンジニアの視点から、分かりやすく丁寧にご説明しますね!これは、「React Flow」や「Svelte Flow」として知られる、ノードベースのUI(ユーザーインターフェース)を構築するための、めちゃくちゃ強力なオープンソースライブラリのことなんです。


なんだ、そうだったのか!「trekhleb/javascript-algorithms」でアルゴリズムとデータ構造を楽しくマスター

「trekhleb/javascript-algorithms」は、GitHubにある、その名の通りJavaScriptで実装されたアルゴリズムとデータ構造の宝庫です。一見すると、「教科書に出てくるような堅苦しいやつか…」と思うかもしれません。でも、実はこれ、ソフトウェアエンジニア、特にJavaScriptをメインで書く私たちにとって、めちゃくちゃ役に立つ「宝の地図」なんです。


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

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


ウェブの無駄を斬る!uBlock Originで快適開発環境を構築する親父の教え

よし、坊主、この頑固親父が、ソフトウェアエンジニアのお前さんに、この「uBlock Origin」ってやつがどう役に立つのか、そしてどうやって俺の秘伝のタレみたいに使いこなすか、とことん教えてやるよ!耳かっぽじってよく聞け!「uBlock Origin」?ああ、一言で言えば「ウェブの無駄をぶった切る、最高の包丁」ってとこだな!


パスワード管理に終止符を! Bitwarden/clientsの導入と活用

登場人物ルパン三世 最新技術に弱い天才泥棒。次元大介 寡黙で頼れる相棒。石川五右衛門 パスワードを毎回手打ちする律儀な剣士。銭形警部 フィッシング詐欺メールに引っかかりがちな捜査の鬼。場所 とあるアジト【コントの始まり】ルパン 「ようし、今夜のターゲットは世界銀行の機密データだぜ!次元、準備はいいか?」


オレオレ詐欺に注意...じゃない!GitHubDailyで良質な情報を安全に手に入れる方法

GitHubDaily/GitHubDaily は、その名の通り、GitHub上で見つけられた高品質で興味深い、実用的なオープンソースプロジェクトを毎日共有しているリポジトリです。新しいプログラミング言語、フレームワーク、開発ツール、面白い技術チュートリアルなど、多岐にわたるプロジェクトが紹介されています。


エンジニア必見!分散システムを楽にするConductor入門:居酒屋から始めるオーケストレーション

大将、ちょっと聞いてくれよ!このConductorってやつが、俺たちの仕事にめっちゃ役立ちそうなんだ。Conductorは、複雑なワークフローを管理するための強力なオーケストレーションプラットフォームだ。マイクロサービスを組み合わせて一つの大きな処理を実行するとき、サービスの呼び出し順序や、途中でエラーが起きたときのリカバリ処理を自動でやってくれるんだ。例えるなら、居酒屋の大将が、お客さんの注文(ワークフロー)を受けて、焼き鳥担当、刺身担当、ドリンク担当(マイクロサービス)に的確に指示を出し、どのタイミングで何を作るか、もし材料が切れたらどうするか、といった全体を仕切る役目を自動でやってくれるようなもんだ。


Web開発の時短術 Bootstrapで叶える爆速デザイン

今日はBootstrapについて、ソフトウェアエンジニアの視点から、その魅力と使い方をたっぷりお伝えしますね。Web開発の世界では、これを知らないとちょっと乗り遅れちゃうかも?というくらい、とっても人気のあるフレームワークなんですよ。一言で言うと、Webサイトの見た目を整えるための道具箱です。