みかづきブログ・カスタム

基本的にはちょちょいのほいです。

Three.jsでクリックされたオブジェクトを判定する 🖱

f:id:kimizuka:20220111110613g:plain

DEMO

https://kimizuka.org/mock/click



Three.jsでオブジェクトがクリックされたことを判定したいなと思い、いろいろ調べてみたのですが、公式ドキュメントに紹介されているやり方で問題なく対応できました。

threejs.org

ソースコード抜粋

window.addEventListener('click', (evt) => {
  const raycaster = new THREE.Raycaster();
  const vector = new THREE.Vector2(
    (evt.clientX / window.innerWidth) * 2 - 1,
    (evt.clientY / window.innerHeight) * -2 + 1
  );

  raycaster.setFromCamera(vector, camera);

  const intersects = raycaster.intersectObjects(scene.children);

  if (intersects.length) {
    if (intersects[0].object.log) {
      window.clearTimeout(timer);
      timer = window.setTimeout(() => intersects[0].object.log(''), 100);
      intersects[0].object.log('click');
    }
  }
});

公式ドキュメントと違う点は、intersectsが空じゃなかった際の処理で、公式ではmaterialのcolorを変更していますが、僕はテクスチャに「click」と表示させました。
何故、Three.Meshにlogなんてメソッドが生えているのかというと、前回作成したログの仕組みを使っているからです。

blog.kimizuka.org

また、公式ドキュメント通り書いたこちらの処理ですが、

const vector = new THREE.Vector2(
  (evt.clientX / window.innerWidth) * 2 - 1,
  (evt.clientY / window.innerHeight) * -2 + 1
);

THREE.Vector2の座標系左上が(-1, -1)、右下が(1, 1)なので、evt.clientX / window.innerWidth、evt.clientY / window.innerHeightの値はそのまま使えず、値を倍にして1を引いたり足したりしてます。

f:id:kimizuka:20220111105753p:plain