Three.js 点击模型,高亮发光模型外轮廓

article/2025/10/8 23:23:36

最近在开发一个功能,在三维场景里有很多模型,需要点击模型,高亮对应的模型,代表选中了该模型。做起来还是稍微麻烦一些的。

具体效果

动画

实现流程

主要的流程还是,

Created with Raphaël 2.3.0 开始 获取鼠标点 射线碰撞 匹配到模型? 匹配成功 高亮轮廓 结束 匹配失败 yes no

关键代码

在Vue项目中,所以参考时需要注意下:

  • 鼠标点击模型
import * as THREE from 'three'//添加监听window.addEventListener('click',event=>{this.clickEvent(event)})  clickEvent(event){//获取在射线上的接触点//获取鼠标坐标let mouse=new THREE.Vector2();let raycaster=new THREE.Raycaster();mouse.x=(event.clientX/window.innerWidth)*2-1;mouse.y=-(event.clientY/window.innerHeight)*2+1;raycaster.setFromCamera(mouse, this.camera);let intersects = raycaster.intersectObjects(this.scene.children);if(intersects&&intersects.length>0){console.log("点击模型")}},;
  • 高亮发光模型外轮廓
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js"
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js"
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js"
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js"//渲染场景
let animate =  () =>{requestAnimationFrame(animate);//渲染外发光renderer.render(scene, camera);if (this.composer) {this.composer.render()}};animate();//高亮显示模型(呼吸灯)outlineObj (selectedObjects) {// 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。this.composer = new EffectComposer(this.renderer)// 新建一个场景通道  为了覆盖到原理来的场景上this.renderPass = new RenderPass(this.scene, this.camera)this.composer.addPass(this.renderPass);// 物体边缘发光通道this.outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), this.scene, this.camera, selectedObjects)this.outlinePass.selectedObjects = selectedObjectsthis.outlinePass.edgeStrength = 15.0 // 边框的亮度this.outlinePass.edgeGlow = 2// 光晕[0,1]this.outlinePass.usePatternTexture = false // 是否使用父级的材质this.outlinePass.edgeThickness = 1.0 // 边框宽度this.outlinePass.downSampleRatio = 1 // 边框弯曲度this.outlinePass.pulsePeriod = 5 // 呼吸闪烁的速度this.outlinePass.visibleEdgeColor.set(parseInt(0xff0000)) // 呼吸显示的颜色this.outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0) // 呼吸消失的颜色this.outlinePass.clear = truethis.composer.addPass(this.outlinePass)// 自定义的着色器通道 作为参数let effectFXAA = new ShaderPass(FXAAShader)effectFXAA.uniforms.resolution.value.set(1 / window.innerWidth, 1 / window.innerHeight)effectFXAA.renderToScreen = truethis.composer.addPass(effectFXAA)},

完整代码

<template><div id="app"><div id="map"></div></div>
</template><script>
import {Scene,PerspectiveCamera,WebGLRenderer,DirectionalLight,MeshBasicMaterial,Mesh,TextureLoader,CylinderGeometry,RepeatWrapping
} from 'three';
import {OBJLoader} from "@/lib/OBJLoader"import * as THREE from 'three'
import { EffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js"
import { RenderPass } from "three/examples/jsm/postprocessing/RenderPass.js"
import { OutlinePass } from "three/examples/jsm/postprocessing/OutlinePass.js"
import { ShaderPass } from "three/examples/jsm/postprocessing/ShaderPass.js"
import { FXAAShader } from "three/examples/jsm/shaders/FXAAShader.js"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"export default {name: 'App',components: {},data(){return{baseY:-20,composer: null,outlinePass: null,renderPass: null,}},mounted() {let scene = new Scene();let camera = new PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);// fov — 摄像机视锥体垂直视野角度// aspect — 摄像机视锥体长宽比// near — 摄像机视锥体近端面// far — 摄像机视锥体远端面let renderer = new WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);let app = document.getElementById("map")app.appendChild(renderer.domElement);//加载场景控制插件let controls = new OrbitControls(camera, renderer.domElement);controls.enableDamping = true;controls.enableZoom = true;controls.autoRotate = false;controls.autoRotateSpeed = 3;controls.enablePan = true;controls.enableKeys = true;controls.keyPanSpeed = 7;controls.keys = {LEFT: 37,UP: 38,RIGHT: 39,BOTTOM: 40}this.controls = controls;//添加一个光源let light = new DirectionalLight(0xffffff);//光源颜色light.position.set(200, 100, 1305);//光源位置scene.add(light);//光源添加到场景中camera.position.y = 30;camera.position.z = 100;this.scene=scene;this.camera=camera;this.renderer=renderer;window.addEventListener('click',event=>{this.clickEvent(event)});this.addBottom(scene)//渲染场景let animate =  () =>{requestAnimationFrame(animate);//渲染外发光renderer.render(scene, camera);if (this.composer) {this.composer.render()}};animate();},methods: {clickEvent(event){//获取在射线上的接触点//获取鼠标坐标let mouse=new THREE.Vector2();let raycaster=new THREE.Raycaster();mouse.x=(event.clientX/window.innerWidth)*2-1;mouse.y=-(event.clientY/window.innerHeight)*2+1;raycaster.setFromCamera(mouse, this.camera);let intersects = raycaster.intersectObjects(this.scene.children);if(intersects&&intersects.length>0){this.outlineObj([intersects[0].object])}},
//高亮显示模型(呼吸灯)outlineObj (selectedObjects) {// 创建一个EffectComposer(效果组合器)对象,然后在该对象上添加后期处理通道。this.composer = new EffectComposer(this.renderer)// 新建一个场景通道  为了覆盖到原理来的场景上this.renderPass = new RenderPass(this.scene, this.camera)this.composer.addPass(this.renderPass);// 物体边缘发光通道this.outlinePass = new OutlinePass(new THREE.Vector2(window.innerWidth, window.innerHeight), this.scene, this.camera, selectedObjects)this.outlinePass.selectedObjects = selectedObjectsthis.outlinePass.edgeStrength = 15.0 // 边框的亮度this.outlinePass.edgeGlow = 2// 光晕[0,1]this.outlinePass.usePatternTexture = false // 是否使用父级的材质this.outlinePass.edgeThickness = 1.0 // 边框宽度this.outlinePass.downSampleRatio = 1 // 边框弯曲度this.outlinePass.pulsePeriod = 5 // 呼吸闪烁的速度this.outlinePass.visibleEdgeColor.set(parseInt(0xff0000)) // 呼吸显示的颜色this.outlinePass.hiddenEdgeColor = new THREE.Color(0, 0, 0) // 呼吸消失的颜色this.outlinePass.clear = truethis.composer.addPass(this.outlinePass)// 自定义的着色器通道 作为参数let effectFXAA = new ShaderPass(FXAAShader)effectFXAA.uniforms.resolution.value.set(1 / window.innerWidth, 1 / window.innerHeight)effectFXAA.renderToScreen = truethis.composer.addPass(effectFXAA)},addBottom(scene) {let loader = new TextureLoader()let texture = loader.load('./bottom.jpg', function (texture) {texture.wrapS = texture.wrapT = RepeatWrapping;texture.offset.set(0, 0);texture.repeat.set(1.57, 1);});let material = new MeshBasicMaterial({map: texture    // 通过map 属性引入图片})let bar = new CylinderGeometry(20, 20, 20, 40, 40, false);//  THREE.CylinderGeometry(radiusTop, radiusBottom, height, radiusSegments, heightSegments, openEnded)//  radiusTop:顶面的半径;// radiusBottom:底面的半径;//  height:是圆柱体的高度;//  radiusSegments:两底面的分段切片;//  heightSegments:侧面的分段切片;//  openEnded:是一个布尔值,表示是否没有顶面和底面,缺省值为false,表示有顶面和底面。let cubeBar = new Mesh(bar, material);cubeBar.position.x = 0cubeBar.position.y = this.baseYscene.add(cubeBar);},}
}
</script><style>
body, html, #app {width: 100%;height: 100%;padding: 0;margin: 0;overflow: hidden;
}#map {width: 100%;height: 100%;position: absolute;left: 0;top: 0;z-index: 1;
}</style>

http://chatgpt.dhexx.cn/article/Rk8baX5g.shtml

相关文章

Three.js--》实现3d汽车模型展览搭建

目录 项目搭建 初始化three.js基础代码 添加汽车模型展示 动态修改汽车模型 今天简单实现一个three.js的小Demo&#xff0c;加强自己对three知识的掌握与学习&#xff0c;只有在项目中才能灵活将所学知识运用起来&#xff0c;话不多说直接开始。 项目搭建 本案例还是借助…

vue3中使用three.js

现在vue3的项目中&#xff0c;大部分是vitevue3typescriptpinia的技术栈 vue3项目中安装three.js pnpm i types/three three 注意&#xff1a;在package.json中查看他们的版本&#xff0c;如果版本不一致的话&#xff0c;可能导致ts不能识别three这个模块 导入three模块 impor…

three.js学习笔记(十九)——后期处理

介绍 后期处理是指在最终图像&#xff08;渲染&#xff09;上添加效果。人们大多在电影制作中使用这种技术&#xff0c;但我们也可以在WebGL中使用。 后期处理可以是略微改善图像或者产生巨大影响效果。 下面链接是Three.js官方文档中一些关于后期处理的示例&#xff1a; http…

JMM--

数据同步的八大原子操作 1.lock 作用于主内存中的变量&#xff0c;把一个变量标记为一条线程的独占状态。 2.unlock 作用于主内存中的变量&#xff0c;把一个处于锁定状态的变量释放出来&#xff0c;释放后的变量才能被其它线程锁定。 3.read 作用于主内存中的变量&#xff0c…

Three.js--》实现3d小岛模型搭建

目录 项目搭建 初始化three.js基础代码 设置环境背景 设置水面样式 添加天空小岛 今天简单实现一个three.js的小Demo&#xff0c;加强自己对three知识的掌握与学习&#xff0c;只有在项目中才能灵活将所学知识运用起来&#xff0c;话不多说直接开始。 项目搭建 本案例还…

JMS简介

jms即Java消息服务&#xff08;Java Message Service&#xff09;应用程序接口是一个Java平台中关于面向消息中间件&#xff08;MOM&#xff09;的API&#xff0c;用于在两个应用程序之间&#xff0c;或分布式系统中发送消息&#xff0c;进行异步通信。Java消息服务是一个与具体…

java jsm_JSM 基础

JMS即Java消息服务(Java Message Service)应用程序接口&#xff0c;是一个Java平台中关于面向消息中间件(MOM)的API&#xff0c;用于在两个应用程序之间&#xff0c;或分布式系统中发送消息&#xff0c;进行异步通信。Java消息服务是一个与具体平台无关的API&#xff0c;绝大多…

JSM

消息中间件 消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流&#xff0c;并基于数据通信来进行分布式系统的集成。通过提供消息传递和消息排队模型&#xff0c;它可以在分布式环境下扩展进程间的通信。对于消息中间件&#xff0c;常见的角色大致也就有Producer&am…

【HLL】使用 HyperLogLog 去重案例

1.概述 HyperLogLog一个常用的场景就是统计网站的UV。 ##基数 简单来说,基数(cardinality,也译作势),是指一个集合(这里的集合允许存在重复元素)中不同元素的个数。例如看下面的集合: {1,2,3,4,5,2,3,9,7} 这个集合有9个元素,但是2和3各出现了两次,因此不重复的元素…

5redis-----------redis高级--GEO-查询附近的人、基数统计算法HLL 、布隆过滤器、缓存雪崩穿透击穿-------全栈式开发44

redis高级 一、GEO查询附近的人二、基数统计算法-HyperLogLog三、布隆过滤器四、缓存雪崩&缓存穿透&#xff08;一&#xff09;缓存雪崩&#xff08;二&#xff09;缓存穿透&#xff08;三&#xff09;缓存击穿 一、GEO查询附近的人 引入 我们所处的任何位置都可以用经纬…

【Hll】Hll HyperLogLog: Cardinality Estimation(基数估计算法源码解析)

1.概述 好文章&#xff0c;转载防丢失 主要是这里有源码&#xff0c;我遇到问题了&#xff0c;问题是flink在累加器中使用的时候&#xff0c;每次累加最终结果是1&#xff0c;2 每次到了2 就会重新回到1&#xff0c;很郁闷于是看看源码 2.背景 我们经常会统计某个字段的dis…

PostgreSQL HLL插件介绍—晟数学院

更多精彩内容:请登录:ke.sandata.com.cn 前言 HLL是 HyperLogLog数据结构的简称。PostgresSQL通过插件的方式引入了这种新的数据类型hll。HyperLogLog是一个具有固定大小,类似于集合结构,用于可调精度的不同值计数。例如,在1280字节的hll数据结构中,它可以在很小的误差…

Redis介绍、优点,缺点、数据类型:字符串、集合、列表、散列、有序集合、HLL、GEO操作

Redis Redis&#xff08;REmote DIctionary Server&#xff09;是一个非常流行的基于内存的轻量级键值数据库&#xff08;key-value database&#xff09;。与其把Redis称为一种数据库&#xff0c;不如说Redis是一种数据结构服务器更为恰当。Redis原生地在内存中实现了多种类型…

java postgresql插件_PostgreSQL HLL插件介绍

前言 HLL是 HyperLogLog数据结构的简称。PostgresSQL通过插件的方式引入了这种新的数据类型hll。HyperLogLog是一个具有固定大小&#xff0c;类似于集合结构&#xff0c;用于可调精度的不同值计数。例如&#xff0c;在1280字节的hll数据结构中&#xff0c;它可以在很小的误差范…

DataSketches HLL Sketch module

上图是官网的介绍&#xff0c;翻译后的意思是此模块提供Apache Druid聚合器为不同的计数基于HLL sketch来自datasketches数据库。摄入的时候这个聚合器创建HLL sketch对象存储在Druid的segments中。在查询的时候sketches被读取并且被合并到一起。最后默认情况下&#xff0c;你可…

UV 统计- HLL算法(JAVA实现)

HLL是什么 HyperLogLog&#xff08;HLL&#xff09;算法经常在数据库中被用来统计某一字段的Distinct Value&#xff0c;比如Redis的HyperLogLog结构。目前在我们项目中用于UV统计。 网上有一篇大佬博文十分深入&#xff1a; https://www.jianshu.com/p/55defda6dcd2 注意&…

HTTP的Referrer Policy

客户端通过设置Referrer Policy来控制是否在请求头中告知服务端请求来源。来源信息写在生成的请求头的referer中。 注意 Referer 实际上是单词 “referrer” 的错误拼写。Referrer-Policy 这个首部并没有延续这个错误拼写。 Referrer Policy的取值&#xff1a; no-referrer 整…

接口基础-HTTP请求中的referrer和Referrer-Policy

本文将介绍一个涉及安全和隐私的http请求头中的字段—referrer&#xff0c;以及如何通过Referrer Policy去修改referrer的值或者是显示与否。 什么是referrer 当一个用户点击当前页面中的一个链接&#xff0c;然后跳转到目标页面时&#xff0c;目标页面会收到一个信息&#x…

Referrer还是Referer? 一个迷人的错误

诗人郑愁予曾经在一首诗中写道&#xff1a;我达达的马蹄是个美丽的错误&#xff0c;我不是归人&#xff0c;是个过客。而对我来说&#xff0c;十九岁之前的我&#xff0c;一样是个沉浸在诗歌中的文艺少年。十九岁之后的我&#xff0c;作为一名程序员&#xff0c;更多的是邂逅各…

HTTP系列之Referer和Referrer policy简介

文章目录 1、前言摘要2、Referer简介3、Referer安全性4、相关术语5、Referrer Policy5.1、no-referrer5.2、no-referrer-when-downgrade5.3、same-origin5.4、origin5.5、strict-origin5.6、origin-when-cross-origin5.7、strict-origin-when-cross-origin5.8、unsafe-url5.9、…