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




より良いNode.js開発のために:nodebestpracticesを読み解く

Node. js開発の「ゴールドスタンダード」とも言える、goldbergyoni/nodebestpracticesという素晴らしいガイドについて、ソフトウェアエンジニアの視点から、キャンプ場の設営になぞらえて、分かりやすくご説明しますね。


Webエンジニア必見!「florinpop17/app-ideas」で基礎力とアウトプットを両立させる導入ガイドとサンプルコード

キリン(真面目で探求心旺盛な雰囲気) 「うむ。キリンとしては、その体系的なプロジェクトのアイデアが、スキルアップという名の『麦芽』をいかに効率良く育ててくれるか、技術的な視点から掘り下げてみたい。」アサヒ(勢いとキレのある雰囲気) 「おっしゃる通り!アサヒは、このアイデア集を『最速でアウトプットを出すための燃料』と捉えています!実践的な導入方法と、すぐに使えるキレの良いコードで、皆様をサポートしますよ!」


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

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


Node.js開発のデファクトスタンダード:Express.jsを用いたシンプルなAPIサーバー構築例

さて、今回ご紹介するのは. ..Aさん (新人エンジニア) 「先輩、Web APIを作りたいんですけど、Node. jsだけだと、URLのルーティングとか、リクエストの処理とか、イチから全部書くのが大変で. ..‍」Bさん (先輩エンジニア) 「おっ、頑張ってるな!でも、そうなんだよな。特に大規模になってくると、生のNode


freeCodeCamp:あなたのキャリアを変える無料プログラミング学習の決定版!

突然ですが、あなたはこんな風に思っていませんか?「プログラミングを学びたいけど、何から始めたらいいか分からない…」 「スキルアップしたいけど、お金がかかるのはちょっと…」 「実戦で使えるコードを書きたいけど、どこで経験を積めばいいの?」もし、一つでも当てはまるなら、今日の放送はあなたのためにあります!


エンジニア必見!「Web-Dev-For-Beginners」で広がるスキルとキャリアの可能性

microsoft/Web-Dev-For-Beginners ですね!ソフトウェアエンジニアの視点から、これがどれだけ役に立つか、そしてどう導入して活用していくかを、フレンドリーに解説しますね!「Web-Dev-For-Beginners」という名前の通り、ウェブ開発の「初心者向け」コンテンツなんですが、実はこれ、ベテランのソフトウェアエンジニアにとっても、めちゃくちゃ価値があるんです!


ダイエット中の俺が解説!Frappe/HRMSで実現するスマート人事!

今日はね、みんながソフトウェアエンジニアとしてバリバリ働く上で、とっても役に立つかもしれない強力なツール、その名も「frappe/hrms」について、コント風に解説していくぞ!ダイエット中の俺と一緒に、この素晴らしいオープンソースHR・給与計算ソフトウェアの魅力に迫ってみよう!


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

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


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

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


酒の飲み比べのように味わうSPlayer:シンプルに潜むエンジニア的メリット

SPlayerは、imsyy/SPlayerというGitHubリポジトリで公開されている、シンプルで使いやすいウェブベースの音楽プレイヤーです。まるで日本酒の飲み比べで、特定の銘柄(音楽プレイヤー)がどんな特徴(機能)を持っているかをじっくりと味わうように、SPlayerをソフトウェアエンジニアの視点から紐解いてみましょう。