在 Three.js 中,可以通过 Raycaster
和 Intersection
来实现对 Mesh
材质或几何体的点击事件捕捉。具体来说,当用户点击画布时,可以发射一条射线(Ray
),检测射线与场景中对象的交点,从而判断是否点击到了某个 Mesh
。
结论
使用 THREE.Raycaster
和鼠标事件监听器,可以轻松实现对 Mesh
的点击事件捕捉,并根据需要获取被点击的材质或几何体信息。
详细展开
1. 核心原理
Raycaster
:用于发射一条射线,检测射线与场景中对象的交点。Intersection
:表示射线与对象的交点信息,包括被点击的对象、交点位置等。- 鼠标事件监听:通过监听鼠标点击事件,获取鼠标在画布上的坐标,并将其转换为标准化设备坐标(NDC)。
2. 实现步骤
以下是实现 Mesh
点击事件捕捉的主要步骤:
- 监听鼠标点击事件。
- 将鼠标坐标转换为标准化设备坐标(NDC)。
- 使用
Raycaster
检测射线与场景中对象的交点。 - 根据交点信息获取被点击的
Mesh
或其材质。
完整示例
以下是一个完整的代码示例,展示如何实现 Mesh
的点击事件捕捉:
// 创建场景、相机和渲染器
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
// 创建几何体和材质
const geometry = new THREE.BoxGeometry();
const material1 = new THREE.MeshBasicMaterial({ color: 0xff0000 });
const material2 = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const material3 = new THREE.MeshBasicMaterial({ color: 0x0000ff });
const materials = [material1, material2, material3];
const cube = new THREE.Mesh(geometry, new THREE.MeshFaceMaterial(materials));
scene.add(cube);
// 设置相机位置
camera.position.z = 5;
// 渲染循环
function animate() {
requestAnimationFrame(animate);
cube.rotation.x += 0.01;
cube.rotation.y += 0.01;
renderer.render(scene, camera);
}
animate();
// 鼠标点击事件监听
let mouse = new THREE.Vector2(); // 存储鼠标坐标
let raycaster = new THREE.Raycaster(); // 创建 Raycaster
// 监听鼠标点击事件
window.addEventListener('click', (event) => {
// 获取鼠标在画布上的坐标
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
// 更新射线
raycaster.setFromCamera(mouse, camera);
// 检测射线与场景中对象的交点
let intersects = raycaster.intersectObjects(scene.children, true);
// 如果有交点
if (intersects.length > 0) {
const intersectedObject = intersects[0].object; // 被点击的对象
const faceIndex = intersects[0].face.materialIndex; // 被点击面的材质索引
console.log('点击了物体:', intersectedObject);
console.log('点击的面使用的材质索引:', faceIndex);
// 改变被点击面的颜色
if (intersectedObject.material instanceof THREE.MeshFaceMaterial) {
intersectedObject.material.materials[faceIndex].color.set(0xffffff); // 设置为白色
}
}
});
代码解析
-
创建
Raycaster
和鼠标监听器:- 使用
THREE.Vector2
存储鼠标坐标。 - 使用
THREE.Raycaster
发射射线。
- 使用
-
将鼠标坐标转换为 NDC:
- 将鼠标在画布上的像素坐标转换为标准化设备坐标(范围为 [-1, 1])。
-
检测交点:
- 使用
raycaster.intersectObjects()
方法检测射线与场景中对象的交点。 - 返回的
intersects
数组包含所有交点信息。
- 使用
-
获取材质索引:
- 如果几何体使用了
THREE.MeshFaceMaterial
,可以通过intersects[0].face.materialIndex
获取被点击面的材质索引。
- 如果几何体使用了
-
修改材质:
- 根据材质索引,动态修改被点击面的颜色或其他属性。
相关延展
1. 支持多种材质
如果几何体使用了多种材质(如 THREE.MeshFaceMaterial
),可以通过 materialIndex
确定被点击面的具体材质。
2. 拾取特定对象
可以通过 raycaster.intersectObjects([specificObject])
限制射线仅检测特定对象。
3. 移动端支持
在移动端,可以监听 touchstart
或 pointerdown
事件代替鼠标点击事件。
window.addEventListener('touchstart', (event) => {
const touch = event.touches[0];
mouse.x = (touch.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(touch.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
if (intersects.length > 0) {
console.log('触摸了物体:', intersects[0].object);
}
});
总结
通过 THREE.Raycaster
和鼠标事件监听器,可以轻松实现对 Mesh
的点击事件捕捉,并根据需要获取被点击的材质或几何体信息。这种方法广泛应用于交互式三维应用中,例如游戏、建筑可视化和虚拟现实。
前端工程师、程序员
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!