Three.jsのcanvas
要素にHTMLの表示を重ねたい時があります。
そのときに必要となるのが、canvas要素上のオブジェクトの座標です。これは、描写面であるcanvas
要素上の座標のことなので、スクリーン座標と言います。
スクリーン座標の算出方法
THREE.Camera
クラスのproject()
メソッドを使うことで、ステージ上のXY座標に変換できます。
// object3D は任意の3Dオブジェクト。
// 3Dオブジェクトのワールド座標を取得する
const worldPosition = object3D.getWorldPosition(new THREE.Vector3());
// スクリーン座標を取得する
const projection = worldPosition.project(camera);
project()
メソッドの戻り値はTHREE.Vector3D
型で、x
とy
はそれぞれ-1.0
~+1.0
の値をとります。z
は3Dオブジェクトの深度を示します。ワールド座標を計算する必要があるので、計算対象の3Dオブジェクトはシーンに追加されている必要があります(シーン直下でなくても問題ありません)。
2D座標の取得には、renderer
インスタンスの幅・高さの値を計算することでcanvas
要素の左上からの座標を求めることができます。
const object3D = new THREE.Mesh(); // 任意の3Dオブジェクト
const width = 960; // rendererの仮サイズ(利用場面において適したサイズに変更ください)
const height = 540;
// 3Dオブジェクトのワールド座標を取得する
const worldPosition = object3D.getWorldPosition(new THREE.Vector3());
// スクリーン座標を取得する
const projection = worldPosition.project(camera);
const sx = (width / 2) * (+projection.x + 1.0);
const sy = (height / 2) * (-projection.y + 1.0);
// スクリーン座標
console.log(sx, sy);
スクリーン座標算出のサンプル
次のサンプルは球体が3D空間内を円周上を移動している様子を表現したものですが、球体のスクリーン座標をテキストで表示するようにしています。
このサンプルではcanvas
に重ねて任意のdiv
要素を重ね合わせます。座標の原点をあわせておきたいので、CSSのposition:absolute
で2つの要素の絶対座標をリセットしておきます。親のdiv
要素の原点を基点としたいのでposition:relative
を指定します。
<!-- 親のタグの基準点をリセット -->
<div style="position:relative;">
<!-- Three.js用のcanvasタグ -->
<canvas style="position: absolute; top: 0; left: 0;"></canvas>
<!-- 座標表示用のdivタグ -->
<div style="position: absolute; top: 0; left: 0;"></div>
</div>