Three.jsチートシート
JavaScript Advent Calendar 2022 24日目の記事です。
Three.jsを軽く試したい時に、毎度調べたり思い出すのが大変なので個人的にまとまっていたら嬉しいという情報をまとめてみました。
Three.jsでとりあえず、何かを表示
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script src="https://unpkg.com/three@0.147.0/build/three.min.js"></script>
<script>
const init = () => {
const width = window.innerWidth;
const height = window.innerHeight;
const canvas = document.getElementById('canvas');
const renderer = new THREE.WebGLRenderer({
canvas,
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, width / height);
camera.position.set(1000, 1000, 1000);
camera.lookAt(0, 0, 0);
const light = new THREE.DirectionalLight(0xffffff, 1);
scene.add(light);
const geometry = new THREE.TorusGeometry(200, 100, 64, 100);
const material = new THREE.MeshLambertMaterial({color: 0xee6666});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const tick = () => {
renderer.render(scene, camera);
requestAnimationFrame(tick);
}
tick();
}
window.addEventListener('DOMContentLoaded', init);
</script>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
</html>
このhtmlをブラウザで開けると、とりあえず表示はできます。
補足
unpkg
NPMに登録されているパッケージをCDNで呼び出せるサービスです。
モジュール版
公式ではモジュール版の読み込みサンプルで説明していますが、とりあえず表示するだけならこれでOKです。
ただし、以下のサイトによると、exapmple/js
が廃止される?ようで、
<script src="https://unpkg.com/three@0.147.0/build/three.min.js"></script>
の記述を足すだけではversion148以降は表示できなくなる可能性があります。
その場合は
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.147.0/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from 'three';
// ここに書いていく
</script>
と書き換えてください。
バージョン
CDNで読み込むバージョンは下記URLで最新を都度確認すると良いでしょう。
パッケージマネージャでインストール
npm install three
公式ではnpmの例を書いていますが、yarnでも大丈夫です。
yarn add three
型定義ファイルの導入
npm install --save-dev @types/three
# もしくは
yarn add --dev @types/three
ちなみに、型定義ファイルは以前同梱されていましたが、今はDefinitelyTypedに移されています。
インタラクティブにオブジェクトを操作
マウスやタッチ操作でカメラを動かしたい場合はOrbitControlsを用いることが一番手軽で定番です。
Three.jsでとりあえず、何かを表示
のindex.htmlにOribitControls
を読み込み、インスタンス化すればマウスやタッチでオブジェクトを動かすことができます。
<script src="https://unpkg.com/three@0.147.0/examples/js/controls/OrbitControls.js"></script>
const controls = new THREE.OrbitControls(camera, canvas);
モジュールでの読み込みの場合は以下に読み変えてください
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.147.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.147.0/examples/jsm/"
}
}
</script>
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
new OrbitControls(camera, canvas);
補足
Three.jsのコアな機能以外はexamples
ディレクトリ以下にあります。
インタラクティブに操作できるようにするアドオンは他にも用意されているので、用途が合わない場合は以下のURLを確認してもいいかもしれません。
外部のオブジェクトを読み込んで表示
// 以下のパスは適宜読み換えてください
// 1
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
// 2
const loader = new OBJLoader();
//3
loader.load('./xxx.obj', (obj) => {
// 4
scene.add(obj);
});
手順を軽く説明すると、
1.OBJLoaderをimpot
2.インスタンス化
3.loadの引数にパスを指定して読み込み
4.コールバック関数内でobjをsceneに追加
です。
補足
Three.jsでとりあえず、何かを表示
のindex.htmlにのソースコードに追加しても動きません。
CORSの設定でブラウザエラーが起こるはずです。
範囲を超えるので説明しませんが、ブラウザの設定を変更したり、WEBサーバーを用意する必要があります。
とにかくアニメーションさせたい
const tick = () => {
mesh.rotation.x += 0.01;
mesh.rotation.y += 0.01;
renderer.render(scene, camera);
requestAnimationFrame(tick);
}
tick();
かなりシンプルな例になりますが、meshをフレームごとに回転させるにはこのようにすれば大丈夫です。
カメラの向きの変更
camera.lookAt(0, 0, 0);
lookAtメソッドに任意の座標を引数に与えるとカメラの向きが変わります。
OribtControlsなどを使用していると競合して動かない場合があるので注意してください。
平行投影のカメラを使用
const camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, -1000, 1000 );
OrthographicCameraを使うことで、遠近感のないカメラに変更することができます。
直方体を追加
const geometry = new THREE.BoxGeometry( 500, 500, 100 )
const material = new THREE.MeshLambertMaterial({color: 0xee6666});
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
他にもいろいろな形がThree.jsには用意されているので、以下で色々探して遊んでみてもいいと思います。
オブジェクトの色を変更
const material = new THREE.MeshLambertMaterial({color: 0xee6666});
マテリアルの引数のカラーコードを変更すればOK。
よくサンプルコードで使用する下記のようなMeshBasicMaterialも引数を変更すればOK。
const material = new THREE.MeshBasicMaterial( {color: 0xee9900} );
リサイズ時にサイズを調整したい
<meta name="viewport" content="width=device-width, initial-scale=1"/>
htmlにレスポンシブ対応でお馴染みのおまじないを追加します。
const resizeHandler = () => {
const width = window.innerWidth;
const height = window.innerHeight;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
}
window.addEventListener('resize', resizeHandler);
このコードをinitの中に書けばリサイズ時に調整されるようになります。
パフォーマンスや保守性を考慮したコードになっていませんが悪しからず。
テクスチャを設定
const texture = new THREE.TextureLoader().load(path);
const material = new THREE.MeshStandardMaterial({
map: texture
});
pathは任意の画像パスを設定してください。
これもまた、loaderを使用するのでCORSの制限に引っかかる可能性があるのでご注意ください。
参考
Discussion