概要
Three.jsでディスプレイによって動きのスピードが早かったり遅かったりといったことが起こると思います。
その対応策を調べました。
問題のコード
公式サイトのコード
import * as THREE from "three";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animate); //⭐️
document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
function animate() {
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
上記は公式のコードです。
このままの状態だと cubeの動きがディスプレイによって早かったり遅かったりします。
仕組みとしては、⭐️をつけた行の setAnimationLoop
関数で animate
関数を呼び出しています。
その呼び出し方がディスプレイのリフレッシュレートに基づいているため、ディスプレイごとに早かったり遅かったりします。
対応策
追加編集したコード
import * as THREE from "three";
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setAnimationLoop(animate);
document.body.appendChild(renderer.domElement);
const geometry = new THREE.BoxGeometry(1, 1, 1);
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
+ const clock = new THREE.Clock(); //①
function animate() {
+ const elapsedTime = clock.getElapsedTime(); //②
- cube.rotation.x += 0.01;
+ cube.rotation.x = elapsedTime; //③
- cube.rotation.y += 0.01;
+ cube.rotation.y = elapsedTime; //③
renderer.render(scene, camera);
}
Clockのインスタンスを作成(①の箇所)し、
そこから getElapsedTime
メソッドの値を elapsedTime
に代入(②の箇所)、
その値を cubeのrotation
に代入(③の箇所)しました。
これで、cubeの動きは時間で制御されるようになったので、
リフレッシュレートに関わらず一定の速さで動くようになりました。
おわりに
すごい細かいこだわりかもしれませんが、何も疑問に思わず requastAnimationFrame
で動かしたりしていたので、勉強になりました