这里写目录标题
前言
基于上篇文章Threejs之光线投射Raycaster我们知道了光线投射的基础用法,在本届我们将使用光线投射进行鼠标交互事件
一、前置准备
1.1 代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script type="module">
// 倒入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import * as THREE from "three";
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera( // 透视相机
45, // 视角 角度数
window.innerWidth / window.innerHeight, // 宽高比 占据屏幕
0.1, // 近平面(相机最近能看到物体)
1000, // 远平面(相机最远能看到物体)
);
camera.position.set(0, 2, 20);
// camera.lookAt(0, 0, 0);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true, // 抗锯齿
});
// 设置渲染器宽高
renderer.setSize(window.innerWidth, window.innerHeight)
// renderer(渲染器)的dom元素添加到我们的HTML文档中
document.body.appendChild(renderer.domElement)
// 开启坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
const geometry = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
const geometry1 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
const geometry2 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
geometry1.position.x = 3;
geometry2.position.x = -3;
scene.add(geometry, geometry1, geometry2);
// 控制器
const control = new OrbitControls(camera, renderer.domElement);
// 开启阻尼惯性,默认值为0.05
control.enableDamping = true;
// 渲染循环动画
function animate() {
// 在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)
requestAnimationFrame(animate);
// 更新控制器。如果没在动画里加上,那必须在摄像机的变换发生任何手动改变后调用
control.update();
renderer.render(scene, camera);
};
// 执行动画
animate();
</script>
</body>
</html>
1.2 效果
可以看到我们在场景中放了三个球,并且设置了坐标轴辅助线。
二、添加交互事件
2.1 代码
添加鼠标交互事件,在鼠标点下去的时候我们去发射一束射线,让与之交互的物体做出一些改变,例如改变物体颜色,添加如下代码:
// 表示2D vector(二维向量)的类
const mouse = new THREE.Vector2();
let geometryArr = [geometry, geometry1, geometry2];
const raycaster = new THREE.Raycaster();
// 监听鼠标点击事件
window.addEventListener("mousedown", (event) => {
// 转换为一个位于二维空间中的点,在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
console.log(mouse.x, mouse.y);
// 使用一个新的原点和方向来更新射线
raycaster.setFromCamera(mouse, camera);
// 每次点击循环设置物体初始颜色,如不设置会导致点击物体后颜色变后不能再变
for(const geometry of geometryArr) {
geometry.material.color.set(0xff0000);
}
// 相交的物体变色
const itgeometrys = raycaster.intersectObjects(geometryArr);
for(const itgeometry of itgeometrys) {
itgeometry.object.material.color.set(0xcc33f4);
}
})
2.2 效果
可以看到我们已经完成了简单的物体交互。不要小瞧了光线投射,在我们与物体交互中起来很大的作用。
三、完整代码
最后给出本届完整代码,如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
html,
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<script type="module">
// 倒入轨道控制器
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import * as THREE from "three";
// 创建场景
const scene = new THREE.Scene();
// 创建相机
const camera = new THREE.PerspectiveCamera( // 透视相机
45, // 视角 角度数
window.innerWidth / window.innerHeight, // 宽高比 占据屏幕
0.1, // 近平面(相机最近能看到物体)
1000, // 远平面(相机最远能看到物体)
);
camera.position.set(0, 2, 20);
// camera.lookAt(0, 0, 0);
// 创建渲染器
const renderer = new THREE.WebGLRenderer({
antialias: true, // 抗锯齿
});
// 设置渲染器宽高
renderer.setSize(window.innerWidth, window.innerHeight)
// renderer(渲染器)的dom元素添加到我们的HTML文档中
document.body.appendChild(renderer.domElement)
// 开启坐标轴辅助器
const axesHelper = new THREE.AxesHelper(5);
scene.add(axesHelper);
const geometry = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
const geometry1 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
const geometry2 = new THREE.Mesh(new THREE.SphereGeometry(1, 32, 16), new THREE.MeshBasicMaterial({color: 0xff0000}));
geometry1.position.x = 3;
geometry2.position.x = -3;
scene.add(geometry, geometry1, geometry2);
// 控制器
const control = new OrbitControls(camera, renderer.domElement);
// 开启阻尼惯性,默认值为0.05
control.enableDamping = true;
// 表示2D vector(二维向量)的类
const mouse = new THREE.Vector2();
let geometryArr = [geometry, geometry1, geometry2];
const raycaster = new THREE.Raycaster();
// 监听鼠标点击事件
window.addEventListener("mousedown", (event) => {
// 转换为一个位于二维空间中的点,在标准化设备坐标中鼠标的二维坐标 —— X分量与Y分量应当在-1到1之间
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
console.log(mouse.x, mouse.y);
// 使用一个新的原点和方向来更新射线
raycaster.setFromCamera(mouse, camera);
// 每次点击循环设置物体初始颜色,如不设置会导致点击物体后颜色变后不能再变
for(const geometry of geometryArr) {
geometry.material.color.set(0xff0000);
}
// 相交的物体变色
const itgeometrys = raycaster.intersectObjects(geometryArr);
for(const itgeometry of itgeometrys) {
itgeometry.object.material.color.set(0xcc33f4);
}
})
// 渲染循环动画
function animate() {
// 在这里我们创建了一个使渲染器能够在每次屏幕刷新时对场景进行绘制的循环(在大多数屏幕上,刷新率一般是60次/秒)
requestAnimationFrame(animate);
// 更新控制器。如果没在动画里加上,那必须在摄像机的变换发生任何手动改变后调用
control.update();
renderer.render(scene, camera);
};
// 执行动画
animate();
</script>
</body>
</html>
标签:Raycaster,Threejs,const,THREE,window,camera,renderer,投射,new From: https://blog.csdn.net/weixin_44103733/article/details/142140623在学习的路上,如果你觉得本文对你有所帮助的话,那就请关注点赞评论三连吧,谢谢,你的肯定是我写博的另一个支持。