LOADING

MiniKano的小窝


 

Three.js 实现双击删除画布上的对应物体

如何实现双击删除画布上的对应物体?

思路:
首先捕捉到鼠标在画布内的WEBGL设备坐标 [-1,1],我们虽然可以通过鼠标事件获取鼠标相对于浏览器的位置,但无法直接获取到WEBGL的对应坐标,我们可以通过数学换算一下:

  • 设备坐标X = (e.clientX/画布宽度)* 2 - 1
  • 设备坐标Y = -(e.clientY/画布宽度)* 2 + 1

第二步:创建一个光线投射器 Raycaster ,光线投射器可以为我们建立相机与鼠标之间的射线,相机鼠标,两点一线。这样我们就可以获取到这个射线穿过的所有实体了。

  1. 创建 Raycaster 实例
  2. 创建二维向量(Vector2)实例,将二维向量的X和Y设置为设备坐标
  3. 使用光线投射器的 setFromCamera 方法,更新摄像机和鼠标之间连线的位置
  4. 使用光线投射器的 intersectObjects 方法,获取这条射线穿过的所有物体,收集为数组
  5. 由于我们只需要删除一个物体,我们直接取数组中第一个元素即可(数组中第一个元素就是离我们(相机)最近的那个物体)
  6. 执行删除方法,删除几何图形,材质对象,然后再删除物体本身,整个删除操作就完成了

代码示例:

.... 创建相机创建场景代码省略
const raycaster = new THREE.Raycaster()//创建一个光线投射器
const pointer = new THREE.Vector2() //创建一个二维向量

window.addEventListener('dblclick' /*双击是dblclick*/, (e) => {
    if (!cubes.length) return

    // 设备坐标X = (e.clientX/画布宽度)* 2 - 1
    // 设备坐标Y = -(e.clientY/画布宽度)* 2 + 1
    pointer.x = (e.clientX / window.innerWidth) * 2 - 1
    pointer.y = -(e.clientY / window.innerHeight) * 2 + 1

    //更新摄像机和鼠标之间的连线(位置)
    raycaster.setFromCamera(pointer, camera)

    //获取这条线穿过了哪些物体,收集成一个数组
    const list = raycaster.intersectObjects(cubes)

    if (!list[0]) return

    //找到这个cube
    const cubeIndex = cubes.findIndex(cube => cube === list[0].object)

    if (cubeIndex === -1) return

    //要删除物体自身的几何图形,和材质对象,再删除物体本身
    cubes[cubeIndex].geometry.dispose()//删除几何图形对象(释放内存)

    for (const material of cubes[cubeIndex].material) {
        //删除几何图形对象(释放内存)
        material.dispose()
    }

    //从场景中删除立方体
    scene.remove(cubes[cubeIndex])

    //拿掉
    cubes.splice(cubeIndex, 1)
})
点赞

发表回复

电子邮件地址不会被公开。必填项已用 * 标注