【Three.js】デルタタイムを使ったアニメーション作成

公開日 :

  • コーディング
デルタタイムを使ったThree.jsのアニメーション

こんにちは!アンドエイチエーのコーディング部です。

本記事では、Three.jsのアニメーション作成において便利な 「elapsedTime()」と「デルタタイム」の概念について詳しく説明します。

まず必要な関数「ティック関数(tick関数)」

まず必要な知識として、ティック関数(tick関数)を簡単に解説します。

ティック関数とは、ブラウザが次のフレームを描画する際に毎回呼び出され、アニメーションの更新を担当する関数です。Three.jsでアニメーションを制御するために非常に重要な役割を担い、ブラウザの性能やデバイスのスペックによって異なるアニメーションの滑らかさを実現してくれます。

通常、ティック関数内で行われる主な処理は、以下の通りです。

  1. オブジェクトの更新
    アニメーション化されたオブジェクトの位置、回転、スケールなどのプロパティを更新します。
  2. カメラの更新
    カメラの位置や方向が変更された場合、それらの変更を反映させます。
  3. レンダリング
    更新されたシーンをレンダラーに渡して、次のフレームを描画します。
  4. 再帰的な呼び出し
    window.requestAnimationFrame() を使用して、次のフレームの描画をブラウザにリクエストします。これにより、ティック関数が連続して呼び出され、アニメーションが滑らかに実行されます。

より具体的に説明すると、以下コードは、アニメーションの更新を処理するためのティック関数を定義しています。

const tick = () => {
    renderer.render(scene,camera);
    window.requestAnimationFrame(tick);
}
tick()
  1. tick という名前の無名のアロー関数を定義
  2. 関数内で、renderer.render(scene, camera) を呼び出し、Three.js のシーンをレンダリング
  3. window.requestAnimationFrame(tick) を呼び出し、ブラウザにアニメーションフレームの更新をリクエスト。これにより、ブラウザが次の再描画のために tick 関数を呼び出すようになります。
  4. 最後に、tick() を呼び出してアニメーションの更新を開始。

ウィンドウのサイズを変更する場合でも、シーン内のオブジェクトをアニメーション化する場合でも、このティック関数を使用することで、キャンバスが新鮮なレンダリングで更新されます。

elapsedTime() で速度や時間経過を調整

では、ティック関数が処理する更新の頻度や範囲をどのように決定するのでしょうか

そこで活躍するのが、elapsedTime()というメソッドです!

elapsedTime() メソッドは、Three.js の Clock オブジェクトを使用して現在の経過時間を返します。この経過時間は、Three.js のアプリケーションが開始されてからの経過時間を秒単位で表します。

この経過時間は、アニメーションのフレームごとに更新されるため、アニメーションの進行に基づいて変化するパラメータや動作を制御するのに便利です。例えば、アニメーションの速度を調整したり、オブジェクトの移動や回転のアニメーションに時間経過を適用したりする際に利用されます。

具体的には、以下のコードになります。

const clock = new THREE.Clock()

const tick = () => {
    const elapsedTime = clock.getElapsedTime();
    renderer.render(scene,camera);
    window.requestAnimationFrame(tick);
}
tick()
  1. THREE.Clock() を使って新しい Clock オブジェクトを作成。Three.js の組み込みクラスであり、時間の経過を追跡するのに使用。
  2. tick という名前のアロー関数を定義し、以下を行う。
    • clock.getElapsedTime() を使って、elapsedTime という変数に経過時間を代入。これにより、アニメーションの経過時間を取得。
    • renderer.render(scene, camera) を呼び出し、Three.js のシーンをレンダリング。
    • window.requestAnimationFrame(tick) を呼び出して、ブラウザにアニメーションフレームの更新をリクエスト。これにより、ブラウザが次の再描画のために tick 関数を呼び出す。
  3. tick() を呼び出して、アニメーションの更新を開始。

また、サインやコサインなどの関数を組み込むことで、アニメーションを柔軟に拡張することができます。

これらの機能は、オブジェクトが特定の範囲内に留まるようにし、ビジュアル要素にダイナミックで制御された動きを加えるのに役立ちます。

See the Pen hybrid scrolling by bibomato (@bibomato) on CodePen.

elapsedTime() を使う問題点も

elapsedTime() の主な課題として、継続的に増加する性質があります。

例えば、GSAPScrollTriggerを導入すると、その問題が分かります。
まずは通常のコード。

See the Pen hybrid scrolling by bibomato (@bibomato) on CodePen.

以下、スクロール位置に応じて回転速度を上げてみましょう。ページを上下にスクロールすると、キューブの動きが速くなったり、スキップが発生したりしているはずです。

See the Pen hybrid scrolling by bibomato (@bibomato) on CodePen.

この不規則な動作は、elapsedTime()の値をスクロール位置に関連付けた結果です。上にスクロールするとき、elapsedTime()は増加し続けますがが、同時に後方に移動します。これは違和感がありますよね。。。

デルタタイム

そこで役立つのが、「デルタタイム」=「時間差」です。

デルタタイムは、elapsedTime()メソッドの各更新間の時間の経過を表します。具体的には、ティック関数が最後に更新された時刻から現在時刻を引くことで計算されます。

const clock = new THREE.Clock();
let previousTime = 0;

const tick = () => {
    const elapsedTime = clock.getElapsedTime();

    // デルタタイム
    const deltaTime = elapsedTime - previousTime;
    previousTime = elapsedTime;
    
    // アニメーション
    mesh.rotation.y += deltaTime * speed.value;

    renderer.render(scene, camera);

    window.requestAnimationFrame(tick);
}

tick();

これにより、アニメーションの中で、デルタタイムをフレームとして捉えることができます。これは、より一貫性のある操作を提供し、スクロールに関連した不規則な動作に対処します。

デルタタイムとelapsedTime()

デルタタイムとelapsedTime()

デルタタイムをスクロールアニメーションに組み込むことで、アニメーションの値がスクロール位置に連動してスムーズに変化します。

この追加機能により、スクロールを操作する際に、視覚的な体験がより滑らかになります。

See the Pen hybrid scrolling by bibomato (@bibomato) on CodePen.

getDelta()

Three.jsは便利な機能として、getDelta()メソッドを提供しています。このメソッドを使うと、デルタタイムを取得するプロセスを簡略化することができます。

この組み込みのメソッドは、計算を単純化し、アニメーションの時間ベースの更新を管理するために、よりアクセスしやすく、効率的にします。

例えば、以下のように使うことができます。

const delta = clock.getDelta();

これにより、アニメーションの更新時にデルタタイムを簡単に取得できます。Web制作の初心者でも理解しやすい、便利な機能です。

const clock = new THREE.Clock()

const tick = () =>
{
    // Delta Time - デルタタイム
    const deltaTime = clock.getDelta()

    mesh.rotation.y += deltaTime * speed.value

    renderer.render(scene,camera)

    window.requestAnimationFrame(tick)
}

tick()

このように、デルタタイムを使ってアニメーションの更新を行うことができます。

まとめ

デルタタイムは、グラフィックス・プログラミングの領域で極めて重要な概念です。この機能を取り入れることで、よりスムーズでリアルなアニメーションを実現することができます。

さらに、アニメーションの複雑なタイミングを調整するのに費やす貴重な時間を節約できる可能性もあります。

デルタタイムを活用することで、より効率的にアニメーションを制御し、高品質なウェブコンテンツを作成できます。ぜひ活用してみてください!

-M

Three.js – JavaScript 3D Library (threejs.org)

合わせて読みたい!