three.js監聽鼠標點擊事件

優化了好幾次的threejs中鼠標點擊事件,直接上代碼。

// 監聽鼠標點擊事件 展示詳情頁面
const onMouseClick = (event) => {
  let raycaster = new THREE.Raycaster()
  let mouse = new THREE.Vector2()
  // 通過鼠標點擊的位置計算出raycaster所需要的點的位置,以屏幕中心爲原點,值的範圍爲-1到1.
  let div3DLeft = div3D.getBoundingClientRect().left
  let div3DTop = div3D.getBoundingClientRect().top
  mouse.x = ((event.clientX - div3DLeft) / div3D.clientWidth) * 2 - 1
  mouse.y = -((event.clientY - div3DTop) / div3D.clientHeight) * 2 + 1
  // 通過鼠標點的位置和當前相機的矩陣計算出raycaster
  raycaster.setFromCamera(mouse, camera)
  // 獲取raycaster直線和所有模型相交的數組集合
  raycastMeshes(clickApp, raycaster)
}
function raycastMeshes (callback, raycaster) {
  let intersects = []
  // 獲取整個場景
  let theScene = scene || new THREE.Scene()
  // 獲取鼠標點擊點的射線
  let theRaycaster = raycaster || new THREE.Raycaster()
  // 對場景及其子節點遍歷
  for (let i in theScene.children) {
    // 如果場景的子節點是Group或者Scene對象
    if (theScene.children[i] instanceof THREE.Group || theScene.children[i] instanceof THREE.Scene) {
      // 場景子節點及其後代,被射線穿過的模型的數組集合
      // intersects = theRaycaster.intersectObjects(theScene.children[i].children, true)
      let rayArr = theRaycaster.intersectObjects(theScene.children[i].children, true)
      intersects.push(...rayArr)
    } else if (theScene.children[i] instanceof THREE.Mesh) {
      // 如果場景的子節點是Mesh網格對象,場景子節點被射線穿過的模型的數組集合
      // intersects.push(theRaycaster.intersectObject(theScene.children[i]))
    }
  }
  intersects = filtersVisibleFalse(intersects) // 過濾掉不可見的
  // 被射線穿過的模型的數組集合
  if (intersects && intersects.length > 0) {
    return callback(intersects)
  } else {
    // this.hiddenDetailDiv()
    return null
  }
}
function filtersVisibleFalse (arr) {
  let arrList = arr
  if (arr && arr.length > 0) {
    arrList = []
    for (let i = 0; i < arr.length; i++) {
      if (arr[i].object.visible) {
        arrList.push(arr[i])
      }
    }
  }
  return arrList
}
function clickApp (intersects) {
  let selectedObjects = null
  if (intersects[0].object !== undefined) {
    console.log(intersects[0].object, '這就是成功點擊到的對象了~')
  }
}

說明注意:
1、div3D是掛載threejs的dom。
2、有些對象是包含了很多children的所以需要遍歷,並push到intersects數組去重。
3、有些對象設置成了不可見,但是仍然會點擊到,所以通過filtersVisibleFalse函數過濾。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章