谷歌网站怎么做推广,海南省网站,网站服务器哪里的好,南昌做网站流程前言
在Web开发中#xff0c;Three.js是一个极为强大的库#xff0c;它让开发者能够轻松地在浏览器中创建和展示3D图形。随着3D技术在网页设计、游戏开发、数据可视化等领域的广泛应用#xff0c;用户与3D场景的交互变得日益重要。而要实现这种交互#xff0c;一个核心的技…前言
在Web开发中Three.js是一个极为强大的库它让开发者能够轻松地在浏览器中创建和展示3D图形。随着3D技术在网页设计、游戏开发、数据可视化等领域的广泛应用用户与3D场景的交互变得日益重要。而要实现这种交互一个核心的技术就是光线投射Raycasting。通过Three.js提供的Raycaster类我们可以检测鼠标或触摸事件在3D空间中的对应位置进而实现点击、悬停等交互效果。本文将深入探讨如何使用Three.js的Raycaster来实现3D场景的交互事件。 光线投射原理及其属性介绍
通过Raycaster拾取模型进行轮廓高亮走这里
什么是Raycasting
Raycasting是一种计算机图形学技术用于确定从一个点通常是观察者的位置或屏幕上的某一点发射出的光线与场景中物体的交点。在3D应用中这一技术常用于模拟光照效果、碰撞检测以及用户交互。简单来说当你在屏幕上点击或触摸时Three.js会从该点向场景发射一条虚拟的射线然后检查这条射线与场景中哪些对象相交从而判断用户点击了哪个对象。 这个类用于进行raycasting光线投射。 光线投射用于进行鼠标拾取在三维空间中计算出鼠标移过了什么物体。
Three.js中的Raycaster
在Three.js中Raycaster类是实现这一功能的关键。它允许你创建一个射线并提供方法来检测这个射线与场景中对象的交点。以下是使用Raycaster的基本步骤
Raycaster实例解释
new THREE.Raycaster(origin, direction, near, far)参数说明 origin - 光线投射的原点Vector3类型。 direction - 射线的方向Vector3类型。 near - 投射近点不能为负值应该小于far其默认值为0 。 far 投射远点不能小于near其默认值为无穷大。 射线交叉对象
创建的光线投射对象有一个intersectObject()方法用来获取射线交叉的对象使用方法如下
const raycaster new THREE.Raycaster(origin, direction, near, far)
const arr raycaster.intersectObjects(object, recursive,optionalTarget)raycaster.intersectObjects()参数 object - 要检查的是否与射线相交的对象Object3D类型。 recursive - 是否检查所有后代可选默认为falseBoolean类型。 optionalTarget - 可选参数放置结果的目标数组。Array类型。若使用这个参数返回检查结果则在每次调用之前必须清空这个数组。 raycaster.intersectObjects()的返回值 distance - 射线投射原点和相交部分之间的距离。 point - 相交部分的坐标。 face - 相交的面。 faceIndex - 相交的面的索引。 object - 相交的物体。 uv - 相交部分的点的UV坐标。 光线投射示例 示例步骤
步骤一、创建射线
const raycaster new THREE.Raycaster()步骤二、用一个二维向量保存鼠标点击画布上的位置
const mouse new THREE.Vector2(1, 1)步骤三、监听窗口事件将x,y轴归一化坐标通过摄像机和鼠标的位置更新色线计算物体和射线的焦点能不能碰到物体碰到物体后随机改变射线照射物体的颜色。
window.addEventListener(click,(e){//设置鼠标向量的x,y值,将XY轴归一化X从-1到1Y为从-1到1所以除以2mouse.x (e.clientX/window.innerWidth)*2-1mouse.y -(e.clientY/window.innerHeight)*21// 通过摄像机和鼠标的位置更新射线raycaster.setFromCamera(mouse,this.camera)//计算物体和射线的焦点能不能碰到物体const intersects raycaster.intersectObjects([sphere1,sphere2,sphere3])if(intersects.length0){intersects[0].object.material.color.set(this.color16())}
})代码解释
raycaster.setFromCamera(mouse,this.camera)每次渲染循环中你需要更新射线的起点通常是相机的位置和方向通常是基于鼠标坐标计算出的向量这里mouse是归一化设备坐标即范围在(-1, -1)到(1, 1)之间的坐标可以通过监听鼠标或触摸事件并使用THREE.Vector2和renderer.domElement.clientWidth/Height进行转换得到。
const intersects raycaster.intersectObjects(scene.children, true);使用raycaster.intersectObjects()方法来检测射线与场景中对象的交点此方法返回一个数组包含了所有与射线相交的对象信息。如果数组不为空说明有对象被选中你可以根据需要处理这些交点信息。
什么是归一化坐标归一化坐标是一个二维坐标仅有X/Y两个维度且X和Y的取值范围均为[-1, 1]坐标原点位于three.js所创建的canvas的中心处。 归一化坐标公式
mouse.x ((event.clientX - container.getBoundingClientRect().left) / container.getBoundingClientRect().width) * 2 - 1;
mouse.y - ((event.clientY - container.getBoundingClientRect().top) / container.getBoundingClientRect().height) * 2 1;以上示例完整代码
templatediv idcontainer/div
/templatescript
import * as THREE from three
// webGL兼容
import WebGL from three/examples/jsm/capabilities/WebGL.js;
import { GUI } from three/examples/jsm/libs/lil-gui.module.min.js;
// 轨道控制器
import { OrbitControls } from three/examples/jsm/controls/OrbitControls.js
//导入RGBRload加载器
import { RGBELoader } from three/examples/jsm/loaders/RGBELoader.js
//导入场景模型加载器
import {GLTFLoader} from three/examples/jsm/loaders/GLTFLoader.js
//导入模型解压器
import {DRACOLoader} from three/examples/jsm/loaders/DRACOLoader.js
export default {name: HomeView,components: {},mounted(){this.init()},data(){return {camera: null, //相机对象scene: null, //场景对象renderer: null, //渲染器对象mesh: null, //网格模型对象Meshmesh2:null,controls:null, //轨道控制器material2:null, //父元素planeMesh:null, //平面rgbeLoacer:null,}},methods:{//随机生成十六进制颜色color16(){//十六进制颜色随机var r Math.floor(Math.random()*256);var g Math.floor(Math.random()*256);var b Math.floor(Math.random()*256);var color #r.toString(16)g.toString(16)b.toString(16);return color;},init(){let container document.body;//创建一个场景this.scene new THREE.Scene()//透视摄像机this.camera new THREE.PerspectiveCamera(75,window.innerWidth/window.innerHeight,0.1,700)//创建渲染器this.renderer new THREE.WebGLRenderer();//渲染器尺寸this.renderer.setSize( window.innerWidth, window.innerHeight ); // 创建三个球const sphere1 new THREE.Mesh(new THREE.SphereGeometry(1,32,32),new THREE.MeshBasicMaterial({color:0x00ff00}))sphere1.position.x -3this.scene.add(sphere1)const sphere2 new THREE.Mesh(new THREE.SphereGeometry(1,32,32),new THREE.MeshBasicMaterial({color:0xff0000}))sphere2.position.x 0this.scene.add(sphere2)const sphere3 new THREE.Mesh(new THREE.SphereGeometry(1,32,32),new THREE.MeshBasicMaterial({color:0x0000ff})) sphere3.position.x 3this.scene.add(sphere3)//创建射线const raycaster new THREE.Raycaster()//用一个二维向量保存鼠标点击画布上的位置const mouse new THREE.Vector2(1, 1) window.addEventListener(click,(e){//设置鼠标向量的x,y值,将XY轴归一化X从-1到1Y为从-1到1所以除以2mouse.x (e.clientX/window.innerWidth)*2-1mouse.y -(e.clientY/window.innerHeight)*21console.log(mouse.x,mouse.y)// 通过摄像机和鼠标的位置更新涉嫌raycaster.setFromCamera(mouse,this.camera)//计算物体和射线的焦点能不能碰到物体const intersects raycaster.intersectObjects([sphere1,sphere2,sphere3])console.log(intersects,intersects)if(intersects.length0){intersects[0].object.material.color.set(this.color16())}})this.scene.backgroundnew THREE.Color(0x999999)// 设置相机位置this.camera.position.z 15; this.camera.position.y 2; this.camera.position.x 2; // 看的方向 this.camera.lookAt(0,0,0)//添加世界坐标辅助器const axesHelper new THREE.AxesHelper(3) this.scene.add( axesHelper );//添加轨道控制器this.controls new OrbitControls(this.camera,this.renderer.domElement)//添加阻尼带有惯性this.controls.enableDamping true//设置阻尼系数this.controls.dampingFactor 0.05//元素中插入canvas对象container.appendChild(this.renderer.domElement); if ( WebGL.isWebGLAvailable() ) {this.animate();} else {const warning WebGL.getWebGLErrorMessage();document.getElementById( document.body ).appendChild( warning );}},//旋转起来animate() {this.controls.update()requestAnimationFrame( this.animate );// this.mesh.rotation.x 0.01;// this.mesh.rotation.y 0.01;this.renderer.render( this.scene, this.camera );}}
}
/script
总结
通过Three.js的Raycaster我们能够以直观且高效的方式实现3D场景中的交互事件。无论是简单的点击反馈还是复杂的拖拽操作Raycasting都是构建互动式3D体验不可或缺的一部分。掌握这项技术无疑能极大提升你的3D应用或游戏的用户体验。希望本文能为你开启探索Three.js交互世界的大门让你的3D项目更加生动有趣。