three.js Raycaster(鼠标点击选中模型)

2024-01-05 00:28

本文主要是介绍three.js Raycaster(鼠标点击选中模型),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

效果:

代码:

<template><div><el-container><el-main><div class="box-card-left"><div id="threejs" style="border: 1px solid red"></div><div class="box-right" style="text-align: left; padding: 10px"><div style="text-align: left">标准设备坐标系:</div><div>three.js Canvas画布具有一个标准设备坐标系,该坐标系的坐标原点是在canvas画布的中间位置,x轴水平向右,y轴竖直向上,标准设备坐标系的坐标值不是绝对值,是相对值,范围是[-1,1],也就是说canvas画布上任何一个位置的坐标,如果用标准设备坐标取衡量,那么坐标的所有值都在-1和 1之间;</div><div style="text-align: left; margin-top: 10px">屏幕坐标转为 标准设备坐标:</div><div style="text-align: left"><pre>// 坐标转化公式addEventListener('click',function(event){const px = event.offsetX;const py = event.offsetY;//屏幕坐标px、py转标准设备坐标x、y//width、height表示canvas画布宽高度const x = (px / width) * 2 - 1;const y = -(py / height) * 2 + 1;})</pre></div></div></div></el-main></el-container></div>
</template>
<script>
// 引入轨道控制器扩展库OrbitControls.js
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
// 效果制作器
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
// 渲染通道
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js";
// 发光描边OutlinePass
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js";export default {data() {return {name: "",scene: null,camera: null,renderer: null,effectComposer: null,mesh: null,geometry: null,group: null,material: null,texture: null,position: null,outlinePass: null,canvasWidth: 1000,canvasHeight: 800,color: [],meshArr: [],};},created() {},mounted() {this.name = this.$route.query.name;const numbers = Array.from({ length: 255 }, (_, i) => i);// const uppercaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');this.color = [...numbers];this.init();},methods: {goBack() {this.$router.go(-1);},addEventListenerFn() {// canvas画布添加监听事件document.getElementById("threejs").addEventListener("click", (event) => {// 1,坐标转换const point_x = event.offsetX; // 获取x方向当前点击点距离原点的距离;向右为正(原点是当前元素的左上角点)const point_y = event.offsetY; // 获取y方向当前点击点距离原点的距离;向下为正(原点是当前元素的左上角点)const x = (point_x / this.canvasWidth) * 2 - 1;const y = -(point_y / this.canvasHeight) * 2 + 1;// 2,创建射线投射器对象,const raycaster = new this.$three.Raycaster();// 3,射线计算,(参数是鼠标点击位置,相机参数)raycaster.setFromCamera(new this.$three.Vector2(x, y), this.camera);// 4,射线交叉计算// const mesh_arr = []// if(!this.scene)return;// this.scene.traverse(m => {//   console.log('m',m);//   if(m.isMesh != undefined && m.isMesh) {//     mesh_arr.push(m);//   }// })const intersects = raycaster.intersectObjects(this.meshArr);if (intersects.length > 0) {if (this.effectComposer) {// intersects[0].object.material.color.set(0xff0000);this.outlinePass.selectedObjects = [intersects[0].object];this.renderFun();}}});},// 随机颜色randomColor() {// 要生成min-max之间的随机数,公式为:Math.random()*(max-min+1)+minlet i = Math.floor(Math.random() * (this.color.length - 0 + 1) + 0);let j = Math.floor(Math.random() * (this.color.length - 0 + 1) + 0);let k = Math.floor(Math.random() * (this.color.length - 0 + 1) + 0);this.position = new this.$three.Vector3(i, j, k);return new this.$three.Color("rgb(" +this.color[i] +", " +this.color[j] +", " +this.color[k] +")");},init() {// 创建场景对象this.scene = new this.$three.Scene();// 创建立方缓存几何体对象for (let i = 0; i < 3; i++) {this.boxGeometry();}// 创建辅助坐标轴对象const axesHelper = new this.$three.AxesHelper(200);this.scene.add(axesHelper);// 创建正交投影相机对象// this.camera = new this.$three.PerspectiveCamera(60,1,0.01,1000);// this.camera.position.set(600,600,600);// this.camera.lookAt(0,0,0);// 创建透视投影相机对象this.camera = new this.$three.OrthographicCamera(-500,500,400,-400,0,1000);this.camera.position.set(200, 200, 200);this.camera.lookAt(0, 0, 0);// const helper = new this.$three.CameraHelper( this.camera );// this.scene.add( helper );// 创建渲染器对象this.renderer = new this.$three.WebGLRenderer();this.renderer.setSize(this.canvasWidth, this.canvasHeight);this.renderer.render(this.scene, this.camera);window.document.getElementById("threejs").appendChild(this.renderer.domElement);// 创建相机空间轨道控制器const controls = new OrbitControls(this.camera, this.renderer.domElement);controls.addEventListener("change", () => {// this.renderer.render(this.scene, this.camera);this.effectComposer.render();});// 调用后处理方法this.effectComposerFn();// 调用 监听  点击事件的方法this.addEventListenerFn();},// 创建盒模型的方法boxGeometry() {// 创建网格基础材质对象const material = new this.$three.MeshBasicMaterial({color: this.randomColor(),});// 创建立方几何体对象const geometry = new this.$three.BoxGeometry(this.position.x,this.position.y,this.position.z);// 创建网格模型对象const mesh = new this.$three.Mesh(geometry, material);if (this.position) {// 网格模型设置位置mesh.position.set(this.position.x, this.position.y, this.position.z);}this.meshArr.push(mesh);this.scene.add(mesh);},// 后处理方法effectComposerFn() {// 创建后处理对象this.effectComposer = new EffectComposer(this.renderer);// 创建后处理渲染器通道对象const renderPass = new RenderPass(this.scene, this.camera);// 后处理对象 添加渲染器通道this.effectComposer.addPass(renderPass);// 创建发光描边对象this.outlinePass = new OutlinePass(new this.$three.Vector2(this.canvasWidth, this.canvasHeight),this.scene,this.camera);// 设置发光描边颜色this.outlinePass.visibleEdgeColor.set(0xE0F409);// 设置发光描边厚度this.outlinePass.edgeThickness = 5;// 描边亮度this.outlinePass.edgeStrength = 20;// 设置发光描边频率this.outlinePass.pulsePeriod = 2;this.effectComposer.addPass(this.outlinePass);},renderFun() {// 调用后处理对象的render方法进行渲染,this.effectComposer.render();window.requestAnimationFrame(this.renderFun);},},
};
</script>
//
<style lang="less" scoped>
.box-card-left {display: flex;align-items: flex-start;flex-direction: row;width: 100%;.box-right {}
}
</style>

这篇关于three.js Raycaster(鼠标点击选中模型)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/571067

相关文章

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

Spring Security基于数据库的ABAC属性权限模型实战开发教程

《SpringSecurity基于数据库的ABAC属性权限模型实战开发教程》:本文主要介绍SpringSecurity基于数据库的ABAC属性权限模型实战开发教程,本文给大家介绍的非常详细,对大... 目录1. 前言2. 权限决策依据RBACABAC综合对比3. 数据库表结构说明4. 实战开始5. MyBA

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

Java的IO模型、Netty原理解析

《Java的IO模型、Netty原理解析》Java的I/O是以流的方式进行数据输入输出的,Java的类库涉及很多领域的IO内容:标准的输入输出,文件的操作、网络上的数据传输流、字符串流、对象流等,这篇... 目录1.什么是IO2.同步与异步、阻塞与非阻塞3.三种IO模型BIO(blocking I/O)NI

基于Flask框架添加多个AI模型的API并进行交互

《基于Flask框架添加多个AI模型的API并进行交互》:本文主要介绍如何基于Flask框架开发AI模型API管理系统,允许用户添加、删除不同AI模型的API密钥,感兴趣的可以了解下... 目录1. 概述2. 后端代码说明2.1 依赖库导入2.2 应用初始化2.3 API 存储字典2.4 路由函数2.5 应

CSS模拟 html 的 title 属性(鼠标悬浮显示提示文字效果)

《CSS模拟html的title属性(鼠标悬浮显示提示文字效果)》:本文主要介绍了如何使用CSS模拟HTML的title属性,通过鼠标悬浮显示提示文字效果,通过设置`.tipBox`和`.tipBox.tipContent`的样式,实现了提示内容的隐藏和显示,详细内容请阅读本文,希望能对你有所帮助... 效

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot