#概要
three.jsで複数のオブジェクトを一気に選択できるselectionBoxって機能があったのでその使用方法と使用感の紹介
#使用環境
OS:Mac
ブラウザ:Chrome
#selectionBoxで何ができるのか?
three.jsのcanvasをドラッグ&ドロップすると始点を左上、終点を右下とした正方形の薄い範囲が示されてその中のオブジェクトを抽出できる
以下にgithubのコードがあるので参考に。githubのthree.jsを落としてこのサンプルを開けば起動できる
https://github.com/mrdoob/three.js/blob/dev/examples/misc_boxselection.html
#使い方
githubのサンプルに沿って使い方の説明。selectionBox以外の説明は省略
主な工程は以下の三つ
- 初期化
- 始点の登録
- 終点の登録
初期化
var selectionBox = new SelectionBox( camera, scene );
var helper = new SelectionHelper( selectionBox, renderer, "selectBox" );
new SelectionBox( camera, scene )は選択範囲のオブジェクトを発見するメイン機能のオブジェクト。sceneを渡してるがこれだとsceneに含まれる全てのオブジェクトを対象とする。対象を減らしたいときは自分で作ったオブジェクトリストを渡す。
ちなみに隠れた第三引数があり検索する奥行きを指定できる(デフォルトは無限)
new SelectionHelper( selectionBox, renderer, "selectBox" )はドラッグ&ドロップした時の範囲を視覚化する薄い青色の四角をだす
以下のようなcssをどっかに登録しとく必要がある
.selectBox {
border: 1px solid #55aaff;
background-color: rgba(75, 160, 255, 0.3);
position: fixed;
}
始点の登録
document.addEventListener("mousedown", function ( event ) {
for ( var item of selectionBox.collection ) {
item.material.emissive = new THREE.Color( 0x000000 );
}
selectionBox.startPoint.set(
( event.clientX / window.innerWidth ) * 2 - 1,
-( event.clientY / window.innerHeight ) * 2 + 1,
0.5
);
});
mousedownを検出したところでクリックの位置を導出してselectionBox.startPoint.set()で登録している
このサンプルでは範囲内のオブジェクトを薄い青色の効果をつけているのでその初期化をここでやっている(for( var item・・・
のところ)
終点の登録
document.addEventListener( "mousemove", function ( event ) {
if ( helper.isDown ) {
for ( var i = 0; i < selectionBox.collection.length; i++ ) {
selectionBox.collection[i].material.emissive = new THREE.Color( 0x000000 );
}
selectionBox.endPoint.set(
( event.clientX / window.innerWidth ) * 2 - 1,
-( event.clientY / window.innerHeight ) * 2 + 1,
0.5
);
var allSelected = selectionBox.select();
for ( var i = 0; i < allSelected.length; i++ ) {
allSelected[i].material.emissive = new THREE.Color( 0x0000ff );
}
}
});
ドラッグ中の終点の登録。
selectionBox.endPoint.set()で始点と同様に終点の登録を行なっている。
終点の登録を行えばselectionBox.select()で今範囲内にあるオブジェクトの計算が行われオブジェクトの取得ができる。
document.addEventListener("mouseup", function ( event ) {
selectionBox.endPoint.set(
(event.clientX / window.innerWidth) * 2 - 1,
-(event.clientY / window.innerHeight) * 2 + 1,
0.5
);
var allSelected = selectionBox.select();
for ( var i = 0; i < allSelected.length; i++ ) {
allSelected[i].material.emissive = new THREE.Color(0x0000ff);
}
});
ドロップ時の終点の登録。ドラッグ中とほぼ同じ処理。範囲内にあるオブジェクトに青い効果をつけて終了
##余談
抽出範囲はドラッグ&ドロップで作られた正方形をカメラの位置と奥行きまでを前後させた時にできる立方体のなかに入ってるオブジェクトを抽出するようになっている。立方体作成にはTHREE.Frustumを使ってる。
また、THREE.Meshを継承したオブジェクトしか抽出できないので他のオブジェクトを抽出するためにはSelectionBox.jsでif ( object instanceof THREE.Mesh ) {
ってなってるところを変更する必要がありそう
#まとめ
コード的には簡単に複数選択が実装できて便利そうだけどMeshしか選択できなかったりscene渡すと全部のオブジェクトが判定対象になったりでちょっと工夫がいる。ちゃんとしたドキュメントも見つからなかったので頑張って元コードを見るしかなさそう