Frontend
チームラボ風の3D空間をThree.jsで作る!実装からパフォーマンス改善まで
チームラボが作り出すような、植物に囲まれた没入感のある空間って素敵ですよね!せっかくなら新しい技術に触れて表現したいと思い、Three.jsを使ってブラウザ上で動く3D空間を作成しました。
1. 開発工程:観察と基本のセットアップ
- 1実際に植物園に行き、インスピレーションを得るための写真撮影
- 2好きな花を20種、草を8種類ピックアップし、透過画像化
- 3Three.jsを用いてシーン、カメラ、レンダラーを初期化
まずは空間のベースとなるセットアップを行います。
import * as THREE from 'three';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(
75, // 視野角 (FOV)
window.innerWidth / window.innerHeight, // アスペクト比
0.1, // 近距離クリップ
1000 // 遠距離クリップ
);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
camera.position.z = 10; // カメラを遠ざける位置2. 空間の構築とユーザーインタラクション
上下左右を植物で囲むために、スプライト(2D画像)をランダムな位置に配置していきます。アーチ型の天井を作るために、X座標に対してsin関数を使って高さを調整し、画像に傾きをつける工夫をしました。
3. ぶつかった壁:パフォーマンスの悪化
開発を進めると、致命的な問題が発生しました。最初の画像読み込みに時間がかかりすぎる上、描写した画像が配列に残り続けるため、時間が経つごとに画面が重くなってしまったのです。PageSpeed Insightsのスコアも真っ赤でした。
画像の重さ
配列の肥大化
レンダリング遅延
UXの低下
4. 解決策:高速化へのアプローチ
快適な空間を取り戻すため、以下の3つのアプローチで徹底的にチューニングを行いました。
- 1画像の軽量化:png/jpgを次世代フォーマットの WebP に変換
- 2CDNの利用:画像のホスティングをDropboxから jsDelivr(CDN) に移行して配信を高速化
- 3動的レンダリング(カリング):カメラのZ座標を監視し、表示領域外のオブジェクトを scene.remove で削除&配列から除外
function removeObjectsOutOfRange(objectsList, zMin, zMax) {
// インデックスのズレを防ぐため、逆順にループ処理
for (let i = objectsList.length - 1; i >= 0; i--) {
const object = objectsList[i];
if (object.position.z < zMin || object.position.z > zMax) {
scene.remove(object); // シーンから削除
objectsList.splice(i, 1); // 配列から削除
}
}
}5. 安定性の担保:ローディング画面の実装
初期ロード時の「止まっている感」をなくすため、TextureLoader を使って並列ロードし、プログレスバーを実装。さらに、フレームレート(FPS)が30以上で安定するまでメイン画面を表示しない「安定性チェッカー」を組み込みました。
