ThreeJs 如何通过鼠标选中物体

537 阅读1分钟

🤔 需求

点击3d场景,获取点击中的对象。

image.png

😎 方案

光线投射Raycaster

Raycaster 光线投射用于进行鼠标拾取(在三维空间中计算出鼠标移过了什么物体)。

🌰 举个栗子

预期效果:点击3d场景中的绿色正方体,并将绿色正方体改成红色正方体

111.gif

  // 3d场景渲染一个正方体
  const scene = new THREE.Scene();
  const camera = new THREE.PerspectiveCamera(
    75,
    window.innerWidth / window.innerHeight,
    0.1,
    1000
  );

  const renderer = new THREE.WebGLRenderer();
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.getElementById("testContainer").appendChild(renderer.domElement);

  const geometry = new THREE.BoxGeometry(1, 1, 1);
  const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
  const cube = new THREE.Mesh(geometry, material);
  scene.add(cube);

  camera.position.z = 5;

  function animate() {
    requestAnimationFrame(animate);

    cube.rotation.x += 0.01;
    cube.rotation.y += 0.01;

    renderer.render(scene, camera);
  }

  animate();
   
  // 鼠标点击监听
  const raycaster = new THREE.Raycaster(); // 初始化raycaster
  const pointer = new THREE.Vector2(); // 鼠标的默认位置是一个二维向量
  window.addEventListener("click", e => {
    pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
    pointer.y = -(e.clientY / window.innerHeight) * 2 + 1;

    raycaster.setFromCamera(pointer, camera) // 计算出**相机照射到鼠标的光线**
    const intersects = raycaster.intersectObjects(scene.children);  //找到和射线相交的对象,返回数组(相交的物体不只有一个)

    for (let i = 0; i < intersects.length; i++) {
      intersects[i].object.material.color.set(0xff0000); //将正方体改成红色
    }
  });