Skip to content

光线投射实现3d场景交互事件

代码

创建三个球,点击其中一个球,改变其颜色

js
import * as THREE from 'three'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js'
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(
  45,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
)

const renderer = new THREE.WebGLRenderer()
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)

camera.position.z = 15;
camera.position.y = 2;
camera.position.x = 2;
camera.lookAt(0, 0, 0)

const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);

const controls = new OrbitControls(camera, renderer.domElement);

controls.enableDamping = true;
controls.dampingFactor = 0.05;

function animate() {
  requestAnimationFrame(animate)
  controls.update()
  renderer.render(scene, camera)
}

animate()


window.addEventListener('resize', () => {
  renderer.setSize(window.innerWidth, innerHeight)
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
})

let eventObj = {
  Fullscreen: function () {
    document.body.requestFullscreen()
  },
  ExitFullscreen: function () {
    document.exitFullscreen()
  }
}

const gui = new GUI()
gui.add(eventObj, 'Fullscreen').name('全屏')
gui.add(eventObj, 'ExitFullscreen').name('退出全屏')

// 创建三个球
const sphere1 = new THREE.Mesh(
  new THREE.SphereGeometry(1, 32, 32),
  new THREE.MeshBasicMaterial({ color: 0x00ff00 })
)
sphere1.position.x = -4
scene.add(sphere1)


const sphere2 = new THREE.Mesh(
  new THREE.SphereGeometry(1, 32, 32),
  new THREE.MeshBasicMaterial({ color: 0x0000ff })
)
scene.add(sphere2)

const sphere3 = new THREE.Mesh(
  new THREE.SphereGeometry(1, 32, 32),
  new THREE.MeshBasicMaterial({ color: 0xff00ff })
)
sphere3.position.x = 4
scene.add(sphere3)

// 创建射线
const raycaster = new THREE.Raycaster()
// 创建鼠标向量
const mouse = new THREE.Vector2()

// 监听鼠标的点击事件
window.addEventListener('click', (event) => {
  // 设置鼠标向量的x, y值
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1
  mouse.y = -((event.clientY / window.innerHeight) * 2 - 1)


  // 通过摄像机和鼠标位置更新射线
  raycaster.setFromCamera(mouse, camera)

  // 计算物体和射线的焦点
  const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3])

  if (intersects.length > 0) {
    if (intersects[0].object.isSelected){
      intersects[0].object.material.color.set(intersects[0].object._originalColor)
      intersects[0].object.isSelected = false // 标记为未选中
      return
    }
    // 自定义的一个属性
    intersects[0].object.isSelected = true // 标记为选中
    intersects[0].object._originalColor = intersects[0].object.material.color.getHex() // 保存原始颜色
    intersects[0].object.material.color.set(0xff0000) // 改变颜色
  }
})

Released under the MIT License.