Three.jsは「Webブラウザの中で3Dの映像やアニメーションを見せるための道具」です。
たとえば、
- ゲームのようにキャラクターや背景が動く
- 商品を360度回して見られる
- 空間の中をカメラが移動するような体験ができる
こういう立体的な見た目を、特別なソフトを入れずに、ただのWebページで再現できるのがThree.jsの力です。
イメージで言うと……
Three.jsは「3Dの舞台セットを作る道具箱」のようなものです。
- 舞台(scene)を作り
- カメラ(camera)を配置し
- 照明(light)を当て
- 役者(3Dの物体=cubeやsphereなど)を登場させ
- アニメーション(動き)を加えられる
といったことが、割と簡単なコードを書くだけで、Webページの中で表示できます。
早速、コードを見てみたいと思います。
立方体を表示するコード
index.html
<!DOCTYPE html>
<html>
<head>
<title>JavaScript Sandbox</title>
<meta charset="UTF-8" />
<body>
<div id="app"></div>
<script src="./index.mjs" type="module"></script>
</body>
</html>
index.mjs
import * as THREE from "three";
// シーンの作成
const scene = new THREE.Scene();
// カメラの作成
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5; // カメラを少し離した位置に設定
// レンダラーの作成
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 立方体のジオメトリとマテリアルを作成
const geometry = new THREE.BoxGeometry(1, 1, 1); // 立方体のジオメトリ
const material = new THREE.MeshNormalMaterial();
// 立方体のメッシュを作成
const cube = new THREE.Mesh(geometry, material);
// シーンに立方体を追加
scene.add(cube);
renderer.render(scene, camera);
// ウィンドウリサイズ時の処理
window.addEventListener("resize", () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
実行結果
See the Pen three_1 by SekappyOfficial (@Sekappy) on CodePen.
立方体を表示しているのですが、これだと動きがないのでただの四角形になっていますね。
ちょっとだけ、動きを持たせたいと思います。
index.mjs
import * as THREE from "three";
// シーンの作成
const scene = new THREE.Scene();
// カメラの作成
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5; // カメラを少し離した位置に設定
// レンダラーの作成
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 立方体のジオメトリとマテリアルを作成
const geometry = new THREE.BoxGeometry(1, 1, 1); // 立方体のジオメトリ
const material = new THREE.MeshNormalMaterial();
// 立方体のメッシュを作成
const cube = new THREE.Mesh(geometry, material);
// シーンに立方体を追加
scene.add(cube);
// アニメーションの更新
function animate() {
requestAnimationFrame(animate);
// 立方体を回転させる
cube.rotation.x += 0.01; // x軸回転
cube.rotation.y += 0.01; // y軸回転
// シーンの描画
renderer.render(scene, camera);
}
// アニメーションを開始
animate();
// ウィンドウリサイズ時の処理
window.addEventListener("resize", () => {
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
});
実行結果
See the Pen three_2 by SekappyOfficial (@Sekappy) on CodePen.
アニメーションのコードを数行書いただけで、ぐるぐる動くようになりました。
また、マウスでアニメーションを操作するコードも書くことができます。
index.mjs
import * as THREE from "three";
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
// シーンを作成
const scene = new THREE.Scene();
// カメラを作成
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 5;
// レンダラーを作成
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 立方体の作成
const geometry = new THREE.BoxGeometry();
const material = new THREE.MeshNormalMaterial();
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
// OrbitControlsの追加(マウス操作を有効にする)
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
// アニメーションループ
function animate() {
requestAnimationFrame(animate);
controls.update(); // 慣性制御に必要
renderer.render(scene, camera);
}
animate();
// リサイズ対応
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
実行結果(マウスでドラッグしてみてください)
See the Pen three_3 by SekappyOfficial (@Sekappy) on CodePen.
アニメーション処理の箇所を修正しただけです。
次は立方体ではなく球体を作成し、会社で食べたお寿司を回転させてみました。
index.mjs
import * as THREE from "three";
// シーンとカメラ
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75,
window.innerWidth / window.innerHeight,
0.1,
1000
);
camera.position.z = 3;
// レンダラー
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// ライト追加
const light = new THREE.DirectionalLight(0xffffff, 1);
light.position.set(2, 2, 2);
scene.add(light);
// テクスチャロード
const textureLoader = new THREE.TextureLoader();
const texture = textureLoader.load("https://pbs.twimg.com/profile_images/1245253215936897024/BGxSUC9D_400x400.jpg");
// 球体作成(外側に絵)
const geometry = new THREE.SphereGeometry(1, 64, 64);
const material = new THREE.MeshStandardMaterial({
map: texture,
side: THREE.FrontSide, // デフォルト。外側に貼る
});
const sphere = new THREE.Mesh(geometry, material);
scene.add(sphere);
// アニメーション
function animate() {
requestAnimationFrame(animate);
sphere.rotation.y += 0.005;
renderer.render(scene, camera);
}
animate();
// リサイズ対応
window.addEventListener("resize", () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
実行結果
See the Pen three_4 by SekappyOfficial (@Sekappy) on CodePen.
マテリアルを変えるだけで、表示する物体を変化させることができます。
Three.js の公式サイトからいろんなサンプルが確認できますので見てみるとよいかもしれません。