Threejs 기본 사례 10번: 클릭 이벤트 시뮬레이션

클릭 시 콘솔 인쇄에 주의하세요.

threejs의 최종 렌더링은 캔버스 형식으로 수행됩니다. 따라서 인터페이스에서 클릭 이벤트를 구현하는 방법은 실제로 캔버스에서 클릭 이벤트를 구현하는 방법이 됩니다. 그러나 실제로 이것은 그 중 하나일 뿐입니다. Threejs는 3차원 공간인데 마우스를 클릭하면 x, y 두자리 데이터로 이동하는데 3차원 세계에서는 마우스 좌표를 어떻게 구하나요? 여기에 표준 장치 좌표가 도입되었습니다.

-1과 1 사이의 값을 갖는 상대값입니다. 장치에서 마우스 움직임의 상대적 위치를 기록하는 데 사용됩니다. 상대적 위치이므로 누구를 기준으로 합니까?

좋아요. 장치 좌표는 웹에서 캔버스 위치 지정 기준점과 다릅니다. 웹에서는 캔버스 위치의 기준점은 왼쪽 상단(0,0)이며, 장치 좌표의 경우 기준점은 캔버스의 중심입니다. 이러한 방식으로 마우스가 움직일 때 웹에서의 마우스 위치를 통해 장치 좌표를 기준으로 마우스의 이동 위치를 얻을 수 있습니다. 즉, sx와 sy의 최종 결과입니다. 물론 3D 세계에서 마우스 포인트의 좌표를 얻고 싶습니다. 또한 장치 좌표를 3D 세계 좌표로 변환하는 작업을 수행해야 하며, 이를 위해서는 이 프로젝트 메소드 worldVector.project(camara)를 통해 실제 변환을 달성해야 합니다.

좌표만 있으면 충분하지 않나요? 아직 아님.

다행스럽게도 threejs는 우리에게 솔루션을 제공합니다. 새로운 3.Raycaster (), Raycaster, 이 클래스는 레이캐스팅 에 사용됩니다 . 레이 캐스팅은 이 클래스의 intersectObjects 메소드를 통해 마우스 선택(3차원 공간에서 마우스가 이동한 객체 계산)에 사용됩니다. 이 광선과 교차하는 장면의 모든 객체를 얻을 수 있습니다. 클릭할지 말지 결정됩니다.

<template>
    <div>
    </div>
  </template>
  
  <script setup>
  import { ref ,reactive, nextTick,onMounted} from 'vue'
  import * as THREE from "three"
  import {OrbitControls} from "three/examples/jsm/controls/OrbitControls"

  const scene=new THREE.Scene()
  //相机
  const camara=new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,1000)
  camara.position.set(0,0,10)
  //几何体
  const cube=new THREE.Mesh(
      new THREE.BoxGeometry(2,2,2),
      new THREE.MeshBasicMaterial({color:"#f90"})
  )
  scene.add(cube)
  
  //渲染器
  const renderder=new THREE.WebGLRenderer({
      antialias:true
  })
  renderder.setSize(window.innerWidth,window.innerHeight)
  renderder.setClearColor("#ccc")
  document.body.appendChild(renderder.domElement)
  

  //控制器
  const control=new OrbitControls(camara,renderder.domElement)
  //渲染函数
  const render=()=>{
      renderder.render(scene,camara)
      requestAnimationFrame(render)
  }
  render()
const mouse=new THREE.Vector2()
let rayCaster=new THREE.Raycaster()
const handlerClick=(e)=>{
  
    mouse.x=(e.clientX/window.innerWidth)*2-1  //通过web中鼠标坐标得到标准屏幕坐标
    mouse.y=-(e.clientY/window.innerHeight)*2+1
    rayCaster.setFromCamera(mouse,camara)   通过摄像机和鼠标位置更新射线

    let intersects=rayCaster.intersectObjects(scene.children) //获取场景中所有与射线相交的物体,结果是一个数组
    console.log("intersects:",intersects)
    if(intersects.length>0){ //length>0则说明有与射线相交的问题。表明点击了
        console.log(intersects[0]) 
    }
}
window.addEventListener("click",handlerClick)

</script>
  <style  scoped>
  .view-box{
      width: 100%;
      height: 100%;
      overflow: hidden;
  }
  .container{
      position: absolute;
      width: 240px;
      height: 240px;
      background: rgba(0,0,0,0.6);
      color:#ccc
  }
  </style>

추천

출처blog.csdn.net/baidu_41601048/article/details/128580584