Reactで深度対応のBoidsアニメーションを作成する:スタイル(とパララックス)で群れを表現
デジタル鳥類学者の皆さん、そして好奇心旺盛なReact開発者の皆さん、ようこそ!🪶 今日はReactとFramer Motionを使って、深度対応かつパララックス速度を持つBoidsアニメーションを作った方法を楽しく深掘りします。ここで紹介するのはありきたりな <canvas>
のボイドシミュレーションではありません—この群れは生き生きとしていて、タッチに反応し、モダンなReactプロジェクトに完全に溶け込みます。
この投稿はアニメーションが好きで、インタラクティブ性を追求したい方、または自分のランディングページに"コードできるぜ"とささやかせたい開発者向けです。
Boidsとは何か?
Boidsは1986年にクレイグ・レイノルズが開発した、小さな鳥や魚の群れの動きを模倣するシミュレーションクリーチャーです。魔法のような動きは3つのルールから生まれます:
- 分離(Separation): 近すぎる隣人と距離を取る
- 整列(Alignment): 友達の向きに合わせて飛ぶ
- 結合(Cohesion): グループの近くにとどまる
結果は?自律的で生命感あふれる群れの動きが生まれ、クリエイターから愛されています。

なぜBoidsにReactを使うのか?
伝統的にはBoidsのシミュレーションはcanvasやWebGLの世界に属します。しかし、今日の高機能なUIやFramer Motionのようなツールを使えば、DOMノードを効率的にアニメートでき、Reactとの統合、インタラクティブ性、さらにはスクロールベースの効果を簡単に取り入れられます。
SEOのヒント: SEOやアクセシビリティが重要なウェブサイト・アプリに最適なアプローチです。かっこいいビジュアルを不可視な
<canvas>
に隠す必要はもうありません!
コンポーネント構成
群れのロジックはひとつのReactコンポーネント <FlockingAnimation />
にまとめています。コードはモジュール化されていて、以下のようなプロップでカスタマイズ可能です:
- 群れのサイズ(自動計算または固定)
- 最大速度と力
- 各ルールの重み付け
- スタイリング用のカスタムクラス
Props:
export type Props = {
className?: string;
initialCount?: number;
maxSpeed?: number;
maxForce?: number;
weights?: Partial<Weights>;
};
Boidの挙動:アルゴリズム
各Boidはクラスインスタンスで、位置、速度、加速度、そして重要な深度(パララックスのため)を保持します。
コアロジックは実際の群れの動きを模倣しています:
flock(boids, weights, maxSpeed, maxForce) {
// 1. 分離、整列、結合のベクトルを計算
// 2. それらに重みをかけて合計
// 3. 加速度に適用
// 4. 加速度をmaxForceで制限
}
各ルールは特定範囲内の近いボイドを調べ、操作ベクトルを算出します:
- 分離: 近すぎるボイドから離れる力
- 整列: 速度を平均化し方向を合わせる力
- 結合: 平均位置に向かって進む力
深度とパララックス:驚きを加える
各ボイドは生成時に0〜1のランダムな深度を持ちます。深度は3つの効果を生みます:
- パララックス速度: 遠いボイドはゆっくり、近いボイドは速く動く
- スケール: 前景のボイドは大きい
- 不透明度: 深いボイドは薄く、近いボイドは鮮明
更新ループ内で処理されます:
const speedFactor = 1 + (1 - this.depth) * PARALLAX_FACTOR;
const dtScalar = dtBase * speedFactor;
描画時にはスケールと不透明度が深度に基づきマッピングされるので、群れは本当に3Dに見えます。これはVRの没入感を味わいながらも面倒な部分は省いたような体験です。
レスポンシブかつ楽しくする工夫
- スクロールに応じたフェード:
useScroll()
とuseTransform()
を使い、スクロールに合わせてアニメーションがフェードアウトし、見飽きさせません。 - ポインター操作: マウスや指でドラッグすると、カーソル位置に新しいボイドが出現。誰だって「群れの支配者」気分を味わいたいですよね?
- ランダムな群れの分布: マウント時にランダムな中心点から複数のボイドが自然に拡散していきます。
ボイドの生成例:
for (let j = 0; j < groupSize; j++) {
const ang = Math.random() * Math.PI * 2;
const rad = Math.random() * SPAWN_RADIUS;
boidsRef.current.push(
new Boid(center.x + Math.cos(ang) * rad, center.y + Math.sin(ang) * rad)
);
}
最適化と開発のヒント
- 可視状態に応じたレンダリング: Intersection Observerを使い、コンポーネントが見えない時は更新を停止。これによりCPUやモバイルバッテリー、ラップトップのファン寿命を節約。
- 効率的な状態更新: Reactの状態更新は必要なときだけ行い、レンダリングコストを抑制。
- モーションバリュー活用: Framer Motionの
motionValue
と<motion.div>
でDOMトランスフォームを滑らかに実現。
フルソースコード
下記リンクから完全なコードを入手可能です!(Framer MotionとTailwind CSSのセットアップはご自身でご用意ください)
まとめ
ReactでBoidsの群れを作るのは少し変わった選択に思えるかもしれませんが、モダンなアニメーションライブラリを使えば、インタラクティブ性、パフォーマンス、そして貴重な開発体験をすべて手に入れられます。