Three.jsにはカメラの動きを自動的に制御する OrbitControls クラスが存在します。

次の用途で役立つ機能です。

  • 周回軌道を描くように、カメラを配置する
  • ポインター操作でカメラの配置やアングルを変更する

導入方法

OrbitControls.jsは、Three.jsライブラリの本体に含まれていないので注意が必要です。CDNで利用するときは、以下のimportmapを記載して、three/addons/というエイリアスを貼ります。

<script type="importmap">
  {
    "imports": {
      "three": "https://cdn.jsdelivr.net/npm/three@0.167.0/build/three.module.js",
      "three/addons/": "https://cdn.jsdelivr.net/npm/three@0.167.0/examples/jsm/"
    }
  }
</script>

処理のほうではimport文で読み込みます。

<script type="module">
import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";

// …
</script>

※公式GitHubのexamples/jsm/controlsフォルダーにJavaScriptファイルにはいっています。該当ファイルはこちらで確認できます。

※Three.js r148(2022年12月リリース)よりexamples/jsフォルダーでの提供はなくなりました。OrbitControlsはES Modulesで利用します。

使い方

OrbitControlsは次の書式で利用します。OrbitControlsクラスのコンストラクターへ、カメラのインスタンスとDOM要素を引数として指定します。これだけで、自動的にマウスと連動してインタラクションが効くようになります。

OrbitControlsクラスの第2引数は、ポインターの操作を受け付ける対象のDOM要素を指定します。多くの利用用途ではdocument.bodycanvas要素が妥当でしょう。以下の例ではdocument.bodyとして指定しています(画面内のどこでもポインター操作を受け付けるようになります)。

// カメラを作成
const camera = new THREE.PerspectiveCamera(/*省略*/);
// カメラの初期座標を設定
camera.position.set(0, 0, 1000);

// カメラコントローラーを作成
const controls = new OrbitControls(camera, document.body);

マウス操作で次のようにカメラを制御できます。

  • オービット(周回軌道): 左ボタンでドラッグ
  • ズーム: マウスホイール
  • パン: 右ボタンでドラッグ

実行可能な最小のサンプルコードはこちらです。次の例では、OrbitControlsクラスの第2引数にcanvas要素を指定しており、ポインター操作の対象をCanvasだけに絞っています。

// サイズを指定
const width = 960;
const height = 540;

// レンダラーを作成
const canvasElement = document.querySelector('#myCanvas')
const renderer = new THREE.WebGLRenderer({
  canvas: canvasElement,
});
renderer.setSize(width, height);

// シーンを作成
const scene = new THREE.Scene();

// カメラを作成
const camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);
camera.position.set(0, 0, 1000);

// カメラコントローラーを作成
const controls = new OrbitControls(camera, canvasElement);

// 形状とマテリアルからメッシュを作成します
const mesh = new THREE.Mesh(
  new THREE.BoxGeometry(300, 300, 300),
  new THREE.MeshNormalMaterial());
scene.add(mesh);

tick();

// 毎フレーム時に実行されるループイベントです
function tick() {
  // レンダリング
  renderer.render(scene, camera);
  requestAnimationFrame(tick);
}

滑らかにコントロールする

OrbitControlsインスタンスのenableDampingdampingFactorプロパティーを設定すると、ドラッグ時にカメラが滑らかに動くようになります。デフォルトだと機械的な動きになってしまいますが、これらのプロパティーを設定するだけで心地良い操作感になります。

enableDampingdampingFactorプロパティーを使う場合は、requestAnimationFrame内でOrbitControlsインスンタンスのupdateメソッドを呼び出す必要があります。

// カメラを作成
const camera = new THREE.PerspectiveCamera(/*省略*/);
// カメラの初期座標を設定
camera.position.set(0, 0, 1000);

// カメラコントローラーを作成
const controls = new OrbitControls(camera, canvasElement);

// 滑らかにカメラコントローラーを制御する
controls.enableDamping = true;
controls.dampingFactor = 0.2;

tick();

// 毎フレーム時に実行されるループイベントです
function tick() {
  // カメラコントローラーを更新
  controls.update();

  // レンダリング
  renderer.render(scene, camera);

  requestAnimationFrame(tick);
}

まとめ

カメラを手軽に制御できるので、小さな作例ではOrbitControlsを使われることが多いです。ただし、手軽である分、カスタマイズの自由度の制限があるので、細かいカメラワークを作ろうとしたらOrbitControlsでは物足りません。カメラの制御はいろんなコードを書いて自作して覚えていくといいでしょう。

次回の記事では、モデリングデータの読み込み方法を説明します。

次の記事へ

関連

Node.js関連のバンドルツールでOrbitControlsを利用する場合は、以下の解説を参照ください。