前回のThree.js入門記事が好評で嬉しい、ゆひゃです。1日でこんなに見てもらえることがなかったので調子に乗って今回もThree.jsに関連した記事を書こうと思います。
前回、npmでインストールをお勧めした「lil-gui」。デモとして提示した3D部分にlil-guiを使っていました。ですが、詳しい使い方を説明していなかったので、今回は使い方と使い道について説明していこうと思います。
lil-guiとは?
lil-guiは、Web上のコントロールパネルから、Webサイトで表示されている要素などを操作することができるGUI要素を生成できるライブラリです。
元々dat-guiという名前で公開されていたので、もしかしたらdat-guiの名前は聞いたことあるかもしれません。
dat-guiの後継として公開されているlil-guiは、元々のdat-guiの機能のほとんどをカバーしています。通常の機能で情報を集める場合は、dat-guiで検索した方が情報が出てくるかもしれません。
lil-guiのあらゆる機能を試してみたい場合はこのページがおすすめです。
インストール方法
前回の記事でも紹介した通り、npmでインストールするのがおすすめです。
npmでインストール
npm install lil-gui --save-dev
npmでインストールしていればJavaScriptでインポートできます。
import GUI from 'lil-gui'
CDNでインストール
npm環境でない場合、CDNでインストールすることもできます。使える場面はThree.jsに限られているわけではないので、こちらのインストールの機会ももしかしたらあるかもしれません。
HTMLのheadタグの中にどちらかを記述します。
<script type="module">
import GUI from 'https://cdn.jsdelivr.net/npm/lil-gui@0.17/+erm'
</script>
<script src="https://cdn.jsdelivr.net/npm/lil-gui@0.17"></script>
<script>
var GUI = lil.GUI
</script>
インストール方法は2種類あります。基本的にはimportがおすすめですが、importはファイルのトップでしか使えないので合う方を使います。
lil-guiの基本的な使い方
lil-guiは本番環境に使うというより、開発環境の補助の役割として使う場面が多いです。なので、さまざまな機能のうち特に知っておくべき機能を紹介します。
数値コントローラー
なんと言ってもこれです。まずはデモを見てみます。
次に書き方です。
const gui = new GUI()
propsObject = { number: 0 }
gui.add( propsObject, 'number' )
書き方はとてもシンプルでこれだけでコントローラーが表示されます。数値の部分を変えると、オブジェクトに格納されてる変数の値が変動します。
初期値や、最小値・最大値、数値の間隔を設定することもできます。
最小値と最大値を決めるとスライダーで数値を調整できるようになります。
propsObject = { number: 10 /**初期値*/ }
gui.add( propsObject, 'number', -10/**最小値*/, 100/**最大値*/, 10/**間隔*/ )
スライダーで変更できる方が視覚的に操作することができますね。スライダーを動かしてみると、10ずつ数値が変更されていることがわかると思います。
addメソッドの後にonChangeメソッドをつなげることで数値が変化した値を使ったイベントを発生させることができます。
使い方はJavaScriptの基本的なイベントリスナーと同じです。
propsObject = { number: 10 }
const inputTarget = document.querySelecter('.jsChangeNumber') //数値を変化させる部分の要素
gui.add( propsObject, 'number, -10, 100, 10 )
.onChange( value => {
inputTarget.innerText = value
})
チェックボックス
チェックボックスはBooleanを変更するだけのシンプルなコントローラーです。
Three.jsの記事でデモを埋め込んでいる時、カメラの「コントローラーの操作を有効にする」で使っていました。
使い方はオブジェクトの値をBooleanにするだけで簡単に使えます。
propsObject = { check: true }
gui.add( propsObject, 'check' )
デバッグ時の活用法として、ライトのデバッグモードのオンオフなどで活躍します。
ライトは場所・範囲や光源の強さなど多くのプロパティを必要とするのでヘルパーが非常に有効です。しかし、ヘルパーを常に表示してると邪魔なのでそんな時に使う機会が多いです。
ライトの使い方の詳細は今後記事にまとめます!
ほかにも、Three.jsに物理エンジンを適用させたとき、当たり判定デバッガーの表示非表示でもよく使っています。
ボタン
ボタンはGUIオブジェクト作成時に関数を渡すことで、押したら登録しておいた関数を実行できるコントローラーです。
カメラコントローラーでぐりぐりした後、カメラの位置や角度を取得するという使い方もできます。
前回の記事で紹介したコードのscene.add( camera )
の下にguiコントローラーのコードを追記します。
...
scene.add( camera )
const gui = new GUI()
const cameraGuiObj = {
getCamera: () => {
const cameraPosition = `\n x:${camera.position.x},\n y:${camera.position.y},\n z:${camera.position.z}`
const cameraRotation = `\n x:${camera.rotation.x},\n y:${camera.rotation.y},\n z:${camera.rotation.z}`
alert('カメラポジション: {'+cameraPosition+'\n}\n\nカメラ角度: {'+cameraRotation+'\n}')
}
}
gui.add( cameraGuiObj, 'getCamera' )
.name( 'カメラ情報を取得' )
13行目、addメソッドの後にnameメソッドを追加しました。nameメソッドはボタンの中の文字や、数値の左にあるラベルの文字を変更することができます。
カメラの初期値をOrbitControlsで視覚的に決めた後に設定する場合などに重宝しそうです。
guiメソッドの外で数値を変更する
lil-guiでカメラの位置や角度を変更すること可能にしながら、OrbitControlsでカメラの位置を変更することもさせたい場合があると思います。
そんな時はgui.add()メソッドの後にlistenメソッドを追加して、orbitControlsのchangeイベントを使ってオブジェクトの値を変更することで対応できます。
...
const cameraObj = {
position: new THREE.Vector3( 0, 0, 0 )
rotation: new THREE.Vector3( 0, 0, 0 )
}
gui.add( cameraObj.position, 'x' ).name( 'Position X' ).listen()
gui.add( cameraObj.position, 'y' ).name( 'Position Y' ).listen()
gui.add( cameraObj.position, 'z' ).name( 'Position Z' ).listen()
gui.add( cameraObj.rotation, 'x' ).name( 'Rotation X' ).listen()
gui.add( cameraObj.rotation, 'y' ).name( 'Rotation Y' ).listen()
gui.add( cameraObj.rotation, 'z' ).name( 'Rotation Z' ).listen()
...
const controls = new OrbitControls( camera, renderer.domElement )
controls.addEventListener( 'change', () => {
cameraObj.position.copy( camera.position )
cameraObj.rotation.copy( camera.rotation )
}
...
4,5行目で new THREE.Vector3()を使ってx,y,z座標を定義しています。
内部的には{x: 0, y: 0, z: 0}と同じように使える上に、cameraの位置や回転をコピーしやすくなるので、THREE.Vector3クラスを使用しました。
7-13行目のgui.addの後にlisten()メソッドを追加しています。
19,20行目は、OrbitControlsによって動かされた時に呼び出されます。
cameraObj.positionとcameraObj.rotationはTHREE.Vector3なので、copyメソッドを使うことができます。copyメソッドは引数に同じTHREE.Vector3の情報を一括代入できるメソッドです。
これを使うことで
cameraObj.position.x = camera.position.x
cameraObj.position.y = camera.position.y
...
..
.
のような煩雑な書き方をする必要がなくなります。
デモを見る前に一旦次に進みます。
グループ化してわかりやすくまとめる
カメラの位置や回転、オブジェクトの位置や回転など、コントローラーが多くなってくるとどんどん見づらくなってくると思います。
そこでguiの要素をグループ化していきます。グループ化は
const cameraGUI = gui.addFolder( 'Camera' )
これだけでグループを作成することができます。新しく定義したcameraGUIは今までのguiと同じように使えます。
cameraGUI.add( cameraObj.position, 'x' ).name( 'Position X' ).listen()
...
..
.
listen()メソッドとグループ化を使ったデモを作成しました。
このデモのコード全文はGitHubにて公開しています。
まとめ
今回はlil-guiの基本的な使い方と、サンプルを使った使い道を紹介しました。
lil-guiはThree.jsでWebサイトを構築する上で必須のライブラリと言っても過言じゃないとさえ思っています。
3DのWebサイトは従来のサイトと異なり、ワイヤーフレームやデザインカンプが非常に作りにくいサイトです。UnityやBlenderのように視覚的にオブジェクトを配置することもできません。
大規模な3Dサイトを開発する場合はもちろんのこと、サイトの一部で3Dを使う場面でも開発段階の頼もしいオトモになると思います。
PR