赞
踩
你完成了一个threejs的模型之后,里面有很多东西,你咋知道你点击的是哪个呢??如何触发你点击的事件呢?再canvas画布中可不能和html事件一样直接使用e.target来完成了哦。如何做到呢?
方法就是从点击的地方创造一条虚拟的从相机射入的射线,来计算这条射线是否穿过了什么几何体,穿过了几个,然后通过方法获取到穿过物体的属性。
- // 创建三个球
- 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);

如果觉得三个球离得太近 可以把相机的z轴位置调高一点 也就是我们的眼睛靠后一点
- camera.position.z = 15;
- // 为了看到z轴
- camera.position.y = 2;
- // 设置x轴
- camera.position.x = 2;
- //设置相机的焦点 (相机看向哪个点)
- camera.lookAt(0, 0, 0);
- // 创建射线
- const raycaster = new THREE.Raycaster();
-
- //创建鼠标向量
- const mouse = new THREE.Vector2();
使用THREE.Raycaster 方法创建一个射线,鼠标向量用来存储后面得到的坐标值
- window.addEventListener("click", (e) => {
- console.log(e.clientX, e.clientY);
- //设置鼠标向量的xy值
- });
- //给window侦听点击事件 获取点击到的地方
- window.addEventListener("click", (e) => {
- console.log(e.clientX, e.clientY);
- //设置鼠标向量的xy值
-
- //设置鼠标向量的xy值
- //公式 可以用边框四个点做测试 或者暂时先记住
- mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
- });
公式是为什么可以用四个点测试一下,然后自己思考一下。或者直接套用。得到的x,y的值就是平面像素转换为三维坐标的x,y值。
- window.addEventListener("click", (e) => {
- console.log(e.clientX, e.clientY);
- //设置鼠标向量的xy值
-
- //设置鼠标向量的xy值
- //公式 可以用边框四个点做测试 或者暂时先记住
- mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
-
- //通过摄像机和鼠标位置更新射线
- raycaster.setFromCamera(mouse, camera);
- });
- window.addEventListener("click", (e) => {
- console.log(e.clientX, e.clientY);
- //设置鼠标向量的xy值
-
- //设置鼠标向量的xy值
- //公式 可以用边框四个点做测试 或者暂时先记住
- mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
-
- //通过摄像机和鼠标位置更新射线
- raycaster.setFromCamera(mouse, camera);
-
- //计算物体和射线的焦点
- const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3]);
- console.log(intersects);
- });

点击空的地方得到的就是一个空数组,点击有球的地方,得到的就是一个数组,数组值中有object属性,代表的就是这个小球的内容,可以通过object属性来设置小球的参数。
当然 也有可能出现两个的情况,所以说我们这时候只用取数组第一个值,用它来设置就好了。我们现在用他来做一个点击就变成红色的交互效果,要求是第二次点击的时候 要变回原有的颜色。
我们的思路就是需要再点击的时候判断他是否已经变过色了,如果没有变过色,就让他变色,并且将现在的颜色存起来。如果变过色,就让他的颜色变回来。
- //给window侦听点击事件 获取点击到的地方
- window.addEventListener("click", (e) => {
- console.log(e.clientX, e.clientY);
- //设置鼠标向量的xy值
-
- //设置鼠标向量的xy值
- //公式 可以用边框四个点做测试 或者暂时先记住
- mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
-
- //通过摄像机和鼠标位置更新射线
- raycaster.setFromCamera(mouse, camera);
-
- //计算物体和射线的焦点
- const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3]);
- // console.log(intersects);
- if (intersects[0].object._isSelect) {
- //设定旧的颜色
- intersects[0].object.material.color.set(intersects[0].object._originColor);
- intersects[0].object._isSelect = false;
- return;
- }
- //添加一个属性 选中状态
- intersects[0].object._isSelect = true;
- //将之前的颜色记录下来
- intersects[0].object._originColor =
- intersects[0].object.material.color.getHex();
- //设定新的颜色
- intersects[0].object.material.color.set(0xff0000);
- });

- //导入 threejs
- import * as THREE from "three";
- //导入轨道控制器
- import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.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);
- // 将渲染器的dom元素添加到body中
- document.body.appendChild(renderer.domElement);
- camera.position.z = 15;
- // 为了看到z轴
- camera.position.y = 2;
- // 设置x轴
- camera.position.x = 2;
- //设置相机的焦点 (相机看向哪个点)
- camera.lookAt(0, 0, 0);
-
- //添加世界坐标辅助器 (红色x轴,绿色y轴,蓝色z轴)一个线段 参数为 线段长度
- const axesHelper = new THREE.AxesHelper(5);
- //添加到场景之中
- scene.add(axesHelper);
-
- // 添加轨道控制器 (修改侦听位置) 一般监听画布的事件 不监听document.body
- const controls = new OrbitControls(camera, renderer.domElement);
-
- //渲染函数
- function animate() {
- controls.update();
- //请求动画帧
- requestAnimationFrame(animate);
- //渲染
- renderer.render(scene, camera);
- }
- animate();
- //渲染
-
- // 监听窗口的变化 重新设置渲染器的大小 画布自适应窗口
- window.addEventListener("resize", () => {
- // 重新设置渲染器的大小
- renderer.setSize(window.innerWidth, window.innerHeight);
- // 重新设置相机的宽高比
- camera.aspect = window.innerWidth / window.innerHeight;
- // 重新计算相机的投影矩阵
- camera.updateProjectionMatrix();
- });
-
- // 创建三个球
- 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侦听点击事件 获取点击到的地方
- window.addEventListener("click", (e) => {
- console.log(e.clientX, e.clientY);
- //设置鼠标向量的xy值
-
- //设置鼠标向量的xy值
- //公式 可以用边框四个点做测试 或者暂时先记住
- mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
- mouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
-
- //通过摄像机和鼠标位置更新射线
- raycaster.setFromCamera(mouse, camera);
-
- //计算物体和射线的焦点
- const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3]);
- // console.log(intersects);
- if (intersects[0].object._isSelect) {
- //设定旧的颜色
- intersects[0].object.material.color.set(intersects[0].object._originColor);
- intersects[0].object._isSelect = false;
- return;
- }
- //添加一个属性 选中状态
- intersects[0].object._isSelect = true;
- //将之前的颜色记录下来
- intersects[0].object._originColor =
- intersects[0].object.material.color.getHex();
- //设定新的颜色
- intersects[0].object.material.color.set(0xff0000);
- });
-
- // //给window侦听点击事件 获取点击到的地方
- // window.addEventListener("click", (e) => {
- // // console.log(e.clientX, e.clientY);
- // //设置鼠标向量的xy值
- // //公式 可以用边框四个点做测试 或者暂时先记住
- // mouse.x = (e.clientX / window.innerWidth) * 2 - 1;
- // mouse.y = -((e.clientY / window.innerHeight) * 2 - 1);
-
- // //测试向量坐标是否正确
- // // console.log(mouse.x, mouse.y);
-
- // //通过摄像机和鼠标位置更新射线
- // raycaster.setFromCamera(mouse, camera);
-
- // //计算物体和射线的焦点
- // const intersects = raycaster.intersectObjects([sphere1, sphere2, sphere3]);
-
- // if (intersects[0].object._isSelect) {
- // //设定旧的颜色
- // intersects[0].object.material.color.set(intersects[0].object._originColor);
- // intersects[0].object._isSelect = false;
- // return;
- // }
- // //添加一个属性 选中状态
- // intersects[0].object._isSelect = true;
- // //将之前的颜色记录下来
- // intersects[0].object._originColor =
- // intersects[0].object.material.color.getHex();
- // //设定新的颜色
- // intersects[0].object.material.color.set(0xff0000);
- // // console.log(intersects);
- // });
- //3D 光线投射技术 完成3D三维场景中事件交互

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。