【threejs教程2】threejs物体点击交互事件

本文详细介绍了如何在Three.js中使用Raycaster处理鼠标与3D物体的点击交互,包括创建可点击物体、初始化Raycaster、鼠标点击事件监听以及物体颜色的切换和恢复机制。
摘要由CSDN通过智能技术生成

【图片效果完整代码位于文章末】

1.基本原理

在Three.js中,为了实现鼠标与3D物体的点击交互,我们主要利用Raycaster类将鼠标在屏幕上的2D坐标转换为3D空间中的射线,然后检测这条射线是否与场景中的3D物体相交。当射线与物体相交时,即视为点击到了该物体。

2.实现步骤

1.创建两个可以被点击的物体

物体的创建基础祥见上一篇文章threejs基础开发应用示例,这里创建了两个方块,我们给他分别命名为“方块1”,“方块2”,并使他们反方向旋转。

function init() {
	camera.position.set(0, 0, 5)
	renderer.setSize(window.innerWidth, window.innerHeight)
	document.body.appendChild(renderer.domElement)
	const geometry = new THREE.BoxGeometry(1, 1, 1)
	const material1 = new THREE.MeshBasicMaterial({
		color: 0xff00a2d7,
		transparent: true,
		opacity: 0.5,
	})
	const material2 = new THREE.MeshBasicMaterial({
		color: 0xffd3e3fd,
		transparent: true,
		opacity: 0.5,
	})
	const cube1 = new THREE.Mesh(geometry, material1)
	const cube2 = new THREE.Mesh(geometry, material2)
	scene.add(cube1, cube2)
	cube1.position.set(0, 0, 0)
	cube1.name = '方块1'
	cube2.position.set(2, 0, 0)
	cube2.name = '方块2'
	cube1.position.x = -2
	controls.update()
	function animate() {
		requestAnimationFrame(animate)
		controls.update()
		cube1.rotation.y += 0.01
		cube2.rotation.y -= 0.01
		renderer.render(scene, camera)
	}
	animate()
}

2.初始化Raycaster与鼠标坐标

// 创建射线投射器
const raycaster = new THREE.Raycaster()
// 鼠标位置
const mouse = new THREE.Vector2()

3.创建鼠标点击事件监听

我们需要创建一个鼠标点击事件的监听,然后将鼠标坐标归一化,从而设置射线的起点和方向。当射线与物体相交时,即可获取到鼠标点击的物体。通过对获取到的物体材质进行设置,即可改变物体的颜色等属性。

   // 鼠标点击事件监听
window.addEventListener('click', mouseClick, false)
function mouseClick(event) {
	// 将鼠标坐标归一化
	mouse.x = (event.clientX / window.innerWidth) * 2 - 1
	mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
	// 设置射线起点为鼠标位置,射线的方向为相机视角方向
	raycaster.setFromCamera(mouse, camera)
	// 计算射线相交
	const intersects = raycaster.intersectObjects(scene.children, true)
	if (intersects.length > 0) {
		// 选中物体
		const selectedObject = intersects[0].object
    alert(`点击了${selectedObject.name}`)
		// 改变当前被点击物体的颜色
		selectedObject.material.color.set(0xff62e258)
	} 
}

4.物体颜色的恢复

通过用一个变量记录上一个被点击的物体状态,可以在点击其他物体时恢复上一个被点击物体的颜色。具体实现如下

// 记录上一个被点击的对象
let lastSelectedObject = null
function mouseClick(event) {
    // 将鼠标坐标归一化
	mouse.x = (event.clientX / window.innerWidth) * 2 - 1
	mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
	// 设置射线起点为鼠标位置,射线的方向为相机视角方向
	raycaster.setFromCamera(mouse, camera)
	// 计算射线相交
	const intersects = raycaster.intersectObjects(scene.children, true)
	if (intersects.length > 0) {
    // 如果之前有选中的物体,将其颜色恢复为初始状态
		if (lastSelectedObject) {
			lastSelectedObject.material.color.set(
				lastSelectedObject.initialColor
			)
		}
		// 选中物体
		const selectedObject = intersects[0].object
    alert(`点击了${selectedObject.name}`)
    // 记录当前选中物体的状态
		selectedObject.initialColor = selectedObject.material.color.clone()
		lastSelectedObject = selectedObject
		// 改变当前被点击物体的颜色
		selectedObject.material.color.set(0xff62e258)
	} else {
		// 如果没有新的物体被选中,恢复上一个选中物体的颜色(如果存在的话)
		if (lastSelectedObject) {
			lastSelectedObject.material.color.set(
				lastSelectedObject.initialColor
			)
		}
	}
}

5.最终完整代码

再添加一些其他显示最终实现代码如下:

<template>
	<div
		style="
			font-size: 24px;
			color: #ffffff;
			text-align: center;
			position: absolute;
			top: 20%;
			left: 50%;
			transform: translate(-50%, -50%);
		"
	>
		{{ msg }}
	</div>
</template>
<script setup>
import * as THREE from 'three'
import { onMounted, ref } from 'vue'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
const msg = ref('')
const scene = new THREE.Scene()
const camera = new THREE.PerspectiveCamera(
	75,
	window.innerWidth / window.innerHeight,
	0.1,
	1000
)
const renderer = new THREE.WebGLRenderer({ antialias: true })
const controls = new OrbitControls(camera, renderer.domElement)
onMounted(() => {
	init()
})
function init() {
	camera.position.set(0, 0, 5)
	renderer.setSize(window.innerWidth, window.innerHeight)
	document.body.appendChild(renderer.domElement)
	const geometry = new THREE.BoxGeometry(1, 1, 1)
	const material1 = new THREE.MeshBasicMaterial({
		color: 0xff00a2d7,
		transparent: true,
		opacity: 0.5,
	})
	const material2 = new THREE.MeshBasicMaterial({
		color: 0xffd3e3fd,
		transparent: true,
		opacity: 0.5,
	})
	const cube1 = new THREE.Mesh(geometry, material1)
	const cube2 = new THREE.Mesh(geometry, material2)
	scene.add(cube1, cube2)
	cube1.position.set(0, 0, 0)
	cube1.name = '方块1'
	cube2.position.set(2, 0, 0)
	cube2.name = '方块2'
	cube1.position.x = -2
	controls.update()
	function animate() {
		requestAnimationFrame(animate)
		controls.update()
		cube1.rotation.y += 0.01
		cube2.rotation.y -= 0.01
		renderer.render(scene, camera)
	}
	animate()
}
// 创建射线投射器
const raycaster = new THREE.Raycaster()
// 鼠标位置
const mouse = new THREE.Vector2()
// 记录上一个被点击的对象
let lastSelectedObject = null
// 鼠标点击事件监听
window.addEventListener('click', mouseClick, false)
function mouseClick(event) {
	console.log('点击事件')
	// 将鼠标坐标归一化
	mouse.x = (event.clientX / window.innerWidth) * 2 - 1
	mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
	// 设置射线起点为鼠标位置,射线的方向为相机视角方向
	raycaster.setFromCamera(mouse, camera)
	// 计算射线相交
	const intersects = raycaster.intersectObjects(scene.children, true)
	if (intersects.length > 0) {
		// 如果之前有选中的物体,将其颜色恢复为初始状态
		if (lastSelectedObject) {
			lastSelectedObject.material.color.set(
				lastSelectedObject.initialColor
			)
		}
		// 选中物体
		const selectedObject = intersects[0].object
		msg.value = `点击了${selectedObject.name}`
		// 记录当前选中物体的状态
		selectedObject.initialColor = selectedObject.material.color.clone()
		lastSelectedObject = selectedObject
		selectedObject.material.color.set(0xff62e258)
	} else {
		// 如果没有新的物体被选中,恢复上一个选中物体的颜色(如果存在的话)
		if (lastSelectedObject) {
			lastSelectedObject.material.color.set(
				lastSelectedObject.initialColor
			)
			msg.value = ''
		}
	}
}
</script>
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Three.js 是一个用于在浏览器中创建和渲染3D图形的JavaScript库。在Three.js中,要实现鼠标可点击的 impulse 交互,需要进行以下步骤: 首先,我们需要添加一个鼠标点击事件监听器。可以使用JavaScript中的addEventListener方法来监听鼠标点击事件。当鼠标点击时,我们可以获取到点击位置的屏幕坐标。 接下来,我们需要将屏幕坐标转换为Three.js中的3D世界坐标。可以使用Three.js提供的Raycaster(射线投射器)来进行坐标转换。Raycaster可以从摄像机位置发射一条射线,然后通过射线与场景中物体的交点来确定点击位置在3D世界中的坐标。 一旦我们获得了3D世界中的坐标,我们可以检查是否有物体点击位置相交。通过调用Raycaster的intersectObjects方法,可以获得与射线相交的物体数组。然后我们可以根据业务需求,对相交的物体进行相应的操作。 例如,我们可以给物体施加力或改变一些属性。其中,impluse可以用来施加一个脉冲力,使物体产生一个瞬时的加速度。 最后,我们需要在渲染循环中更新场景,并处理鼠标点击事件。渲染循环是由requestAnimationFrame方法驱动,它会根据屏幕刷新率反复调用渲染函数,以更新画面。在渲染函数中,我们可以检查鼠标点击事件是否发生,并根据点击位置进行相应的处理。 总而言之,通过添加鼠标点击事件监听器、使用射线投射器转换点击坐标、检测与物体的交点、施加脉冲力或改变属性等步骤,我们可以在Three.js中实现鼠标可点击的 impulse 交互

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有只老羊在发呆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值