找回密码
 立即注册
首页 业界区 业界 ThreeJs-16智慧城市项目(重磅以及未来发展ai) ...

ThreeJs-16智慧城市项目(重磅以及未来发展ai)

巨到 2025-6-2 00:33:58
1.gif

项目源码:https://gitee.com/hq8466/threecity-com
写在前面:很早就弄完了的,只是一直说挑个黄道吉日发上来,托了这么久也没选到什么节日,今天天气不错就发了吧,然后后面可能更新技术方面的东西就减少次数了,现在ai发展情况下,学习成本贬低,很多东西并不需要钻研太深了,你只需要钻研一个东西ai,这段时间也简单的研究了下一些在人工智能蓬勃发展时代下,对于编程有些什么冲击,就我目前的研究成果,我一个人可以做到不只是前端的活,包括前后端,threejs,3D建模等等都可以一个人完成,所以后面可以陆续发一些如何ai编程的东西上来,当然学习不止,因为不管是什么你都得会,因为出现问题还得通过你的基础去解决。
一.Vue创建智慧城市项目并配置glsl写法支持

这里先说一个问题,关于遇到一格式化就出现vue3一格式化就这个以前也遇到过
就是格式化插件的问题我用的vetur,有点问题换成就可以了
2.png

3.png

后续又知道了其实vetur还带有代码提示,还不能删用处挺大,那么继续用vetur可以加一个ts的语言
4.png

第二个问题,后面会写特效,所以肯定要用shader,但是发现项目并不支持
5.png

6.png

7.png

不管是webpack还是vite都要先配置一下对于glsl文件的支持,这里是webpack
8.png

二.项目基础代码结构分解

首先我们有一个组件,专门搭建场景
首先把一些该先声明的three直接放在setup函数里面
9.png

这里要注意以前是放在body,现在是放在这个组件里面
10.png

11.png

在onmounted钩子里面拿到div并把渲染器给进去
12.png

13.png

14.png

当然真实场景也不会把所有这些东西全放在scripts里面,一般会分模块来放,创建一个three文件夹
15.png

就是把各模块封装导出,在该引用的地方导入
16.png

17.png

这里面有两个特殊的,一个是init放一些不需要导出,一开始就可以初始化的东西
还有一个是后面会创建各种各样的物体,所以其实可以封装一个传参数进去返回各种物体的函数,createMesh这里还没有封装
18.png

19.png

这样下来在组件里面就没有太多写的了
20.png

21.png

三.生成城市建筑模型

推荐一个网站https://cadmapper.com/pro/home
可以根据框出来的范围,生成城市模型,直接导出,但是导出来是一个.dxf的文件
需要下载一个软件 Autodesk3dsmax的软件把这个文件导入,导出可以选择.dxf或者直接一个白模.fbx格式导出
选择要导出的模型
22.png

导出后再次用Blender导入,然后可以跳下位置按G键,x轴就是x键,y轴移动就是y键最后就可以通过Blender导出为glb格式
加载模型,再次封装结构
再次来个专门建物体的文件夹
23.png

createmesh就调用函数
24.png

每个物体声明自己的函数
25.png

这里虽然模型加载进来了,但是发现没有出现,这是因为模型的材质颜色本身就是黑色没有颜色,所以这里需要改一下所有物体的材质颜色
traverse函数拿到该模型场景下面所有的子元素
只有是要展示的物体时才改他的材质,并且这里颜色不能直接修改
26.png

此时如果发现一进来因为模型很大,想远点看
27.png

28.png

四.城市模型科技感渐变效果

要弄特效肯定需要shader
创建一个文件夹这个函数传值材质,对这个材质着色器修改都写在里面
29.png

在刚才创建模型那里把材质传进来
30.png

31.png

渐变效果:由城市的底部到顶部给城市的建模建筑物来一个渐变的颜色
这里大概的一个思路是这样的,我可以通过一个方法得到整个城市建模的落差,也就是最高度减去最低得到城市的落差高度,这个时候把每个建筑物的材质传进着色器函数,修改他们的着色器,会用到之前的一个混合,前三维变量就是它本身的颜色,第四维变量就是设置想要建筑物最高的颜色,实现一个过渡渐变,而混合就是把这两个颜色混合在一起,然后混合的比例就是通过建筑物的y轴高度/刚才的落差的百分比
32.png

33.png

34.png

这个时候就可以拿到真个城市建模高度差
35.png

36.png

五.多层着色器特效合并与城市光圈扩散效果

5.1布局

大概实现效果就是沿着城市中心又一圈一圈往外扩散的光圈
先重构一下布局,在之前的方法里面对城市建模进行了渐变但那只是一个特效所以可以封装成一个函数传需要的参数进来就可以了
37.png

这里再封装一个光圈扩散的效果
需要注意的是我们为了对片段着色器进行无限往后面添加代码,可以一直往后面添加一个这个标识
之前是直接在最后一行代码添加
38.png

直接在最后一行添加一个注释
39.png

后面要改的话
40.png

5.2逻辑

大概的一个逻辑就是我们需要设置一个中心顶点的变量以及时间和扩散的条带宽度
41.png

难点逻辑理解
42.png

43.png

44.gif

六.直线光带掠过城市效果

6.1 x轴

想实现直线扫过的效果其实跟刚才差不多,只不过没有了半径中心点这些的计算,然后覆盖范围就变成了x轴或者y轴等等
45.png

但是要注意此时光线是从中间出发
46.gif

要实现从底部出发,可以修改时间,因为时间是会和x轴相减的
47.png

但是还要同步修改动画需要走完的时间值
48.png

49.gif

如果想斜着来,那就同时修改x轴和z轴
50.png

51.gif

6.2 y轴

那么y轴其实也就是从下到上可以实现别样的效果
最开始的值呢就从0开始到500
然后把position变成y,动画时间可以改短点
52.png

53.gif

七.利用tube特性生成带纹理图案飞线

就是从一个建筑物到另一个建筑物有一条链接的线,这里我们可以用tube管道材质完成
54.png

这里的思路是这样,加载模型之后,我们封装一个类,传入从哪里到哪里,就可以生成这里到那里的管道材质飞线,然后把它加入场景即可
在最开始导入模型那里
55.png

要设置管道长度可以设置顶点参数,要设置粗细,可以设置管道几何体第三个参数
56.png

57.png

7.1设置纹理

58.png

设置纹理图片
59.png

60.png

有个问题只显示了一半
此时可以在y轴上让他重复两遍
61.png

62.png

63.png

创建动画,由刚才的值,箭头要动应该是偏移x轴
64.png

65.gif

7.2 着色器实现

着色器也能实现同样的效果,和纹理相比可以实现类似彗星效果
这个后面有时间可以看一下意义不大
66.gif

八.智慧城市光墙特效

给城市中间来一个光墙效果,这里我们采用圆柱几何体来做
67.png

8.1 布局

因为这是一个物体,所以放在mesh里面,同样创建一个class,new出来
一样的在建模这里new
68.png

69.png

先简单构建个黄色
70.png

71.png

72.png

73.png

8.2 实现渐变

其实这里渐变的逻辑跟之前一样,城市模型渐变效果的时候,就是拿到高度,然后成为混合比例的颜色去和黄色混合一下颜色就渐变了
在封装类这边传进来高度差值
新版three这样获取高度,要手动计算
74.png

先获取顶点
75.png

片段着色器,跟之前一样获取混合比例,直接把颜色给到透明度参数
76.png

此时
77.png

1-翻转过来
78.png

如果还想动画
yoyo表示过去后又原样回来
79.png

80.gif

九.智慧城市雷达扫描特效

9.1 布局

基本布局跟上面光墙差不多先拿来修改一下,只是不再是圆柱体,而是平面
81.png

82.png

此时位置在正中心
83.png

为了在一个位置边缘,并且要翻转过来
84.png

85.png

9.2 实现

之前在讲着色器有个案例,这里简单回顾下
86.png

这里使用了vuv平面顶点
87.png

88.png

如果想要动起来,配合动画的时间函数,而且还要配合之前shaderbook的旋转函数,直接套用即可
89.png

90.png

91.gif

十.封装3D警告标识与点击提示事件

10.1 布局

3D警告标识,就是一栋建筑物比如着火了,那么在其头上来一个标识图片,要实现这个效果需要制作 精灵图
92.png

他最后也是创建一个物体,所以这里也是封装一个类,拿到他的物体
93.png

94.png

95.png

10.2 实现3D物体点击事件

注意这里封装思想
在创建new这里拿到class,假装调用他的点击事件,这个其实也是封装在类里面的方法 注意不再是constructor里面的属性
96.png

封装大概思路
97.png

此时是点击任意位置都可以实现点击事件
如果还要只点击这个图标才触发那么这里的原理还是利用投射光线
原理:通过鼠标点击位置和摄像机打一束光出去,我们如果能判断打出去的光里面如果有要点击的这个物体,那么就可以去执行这个回调
98.png

99.gif

如果你想拿到点击的这个事件对象或者说物体
100.png

101.png

102.png

十一.添加智慧城市天空盒子和设置抗锯齿效果

就是设置整个场景的一个大背景
以我这里这几张图为例
设置天空盒子图片切图可自行百度
103.png

![GIF](F:\前端\阶段十二 threeJS\04-光照与阴影\16智慧城市项目.assets\GIF-17362612172353.gif)
开启抗锯齿
目前可以看到建筑物边缘锯齿感还是比较重
104.png

105.png

106.png

十二.智慧城市大屏样式与结构

一个3D项目如果要配合数字孪生等,那是需要大屏支持的,也就是在3D表面再来左右两边2D,配合一起展示,像我这个就可以看城市的火警之类的,并且点击大屏可以对3D做出对应的显示操作
12.1 布局

首先布局,需要跟3D同级再来一个组件
107.png

大概布局占满全屏,分为左和右,zindex跟3D一样
108.png

109.png

110.png

12.2 Pointer-events穿透事件

现在的话由于2D大屏在前,所以像去转动3D等一些操作,是不行的,我们可以设置让2D点击事件穿透过去
111.png

那么此时左右两边的2D点击事件就不会生效了,我们可以单独设置这个2D元素的pointevent的css
十三. 智慧城市动态数字面板动画

13.1 根据apifox制造mock数据

下载好后创建一个项目
112.png

导入数据选择apifox
113.png

回来之后可以运行调试,注意切换mock环境
114.png

创建接口环境
115.png

13.2 发起请求并动态生成数据

发起请求
116.png

117.png

接下来把接口用在页面上
注意这里对数据做出处理,拿回来的数据一共四个对象,我也是放在对象里面并不是数组,这个大对象有四个属性分别是iot、event等,并且给number属性给一个初始值0
然后这里做出了一个处理,就是我想number数字是动态慢慢增长生成的,不是一下子数据就上来了,那么动画效果就可以用到gasp来实现,单独实现number属性
118.png

这边遍历数据注意此时数据是
119.png

遍历的是一个对象,遍历对象,前面是key后面是value,所以这里的item实际上就是iot这个对象,所以可以直接用.name
120.png

121.gif

如果不想要小数,只显示整数
122.png

123.png

124.gif

13.3 通过接口生成城市事件列表

也就是右边的部分,右边是一个事件列表,通过接口获取,有多少火情等一些灾害显示
先调用接口获取参数
125.png

126.png

一样的传过来
127.png

遍历循环
128.png

对于这里图片的处理,我们一共有三种分别对应治安电力和火警这里可以创造一个对象,key就是name,value就是图片地址,通过name去匹配是什么图片
129.png

130.png

然后再图片右边我们可以显示发生的时间,但是通过刚才的接口得知没得时间字段,这里展示用apifox快速创建一个接口字段
直接在修改接口里面新增一个子节点,并且可以修改类型和要什么样的数据都可以
131.png

132.png

133.png

13.4 城市事件列表动态生成雷达-飞线-光墙

这是一个复杂大的流程
首先把列表也给3D传一份
134.png

135.png

136.png

说下这里的逻辑这个接口返回会有position也就是坐标
我们之前封装过一个警告的雪碧图
137.png

基于这个封装来修改,new这个类,需要三个参数,分别是type也就是name,用来匹配什么样的标志,然后是position也就是位置,还有就是color标志的颜色也可以传,当然也可以给个默认值
改造对应的图标
138.png

改造位置
139.png

这两个接口每次刷新都会有随机数据,所以这里制造一种长链接的效果
每隔一段时间就刷新,有不同的灾害发生用定时器实现
140.png

这边3D需要拿到每次不同的数据,并且把参数传进刚才封装的类里面,用watch来实现
每五秒获取一次数据
141.png

142.png

每一次来新的数据,将position改造一下,让他只在-几到几的范围内,因为整个建筑物没有高于这个值得高度
143.png

但是现在有个问题就是,会有新增的进来,但是之前的也不会删除
144.png

这里我们采用3D物体上有一个方法
145.png

这里我们采用这个方法,在封装类里面,跟之前的点击事件同级封装一个remove方法,将当前这个mesh和父级删除,注意mesh的材质和几何体调用dispose表示不受影响
146.png

然后我们定义一个空数组,每次数据有变化都进行一个全清的操作,同时下面把这次的新数据给到数组里面
147.png

148.gif

第二个问题现在存在深度检测
也就是两个叠加在一起应该混合一下成为一体的颜色
149.png

给材质设置一下
150.png

151.png

![GIF 2025-1-15 10-14-56](F:\前端\阶段十二 threeJS\04-光照与阴影\16智慧城市项目.assets\GIF 2025-1-15 10-14-56-1736910121965-4.gif)
接下来根据火灾警情等动态生成雷达光墙
光墙
根据火灾动态生成光墙,光墙就是圆柱体向外扩展那一个
这是原来封装的类
152.png

现在改造一下,圆柱体的两个半径我们输入参数,半径变化范围也是我们自己来
153.png

这里的逻辑是这样的,创建一个对象是三种警情的名字,然后在遍历创建之前雪碧图那里通过名字把每一次产生的警情position数据传进来,给到光墙,半径和变化的长度是固定的就可以实现,根据数据在不同的地方产生光墙
154.png

155.png

这里封装位置别忘记改
156.png

157.gif

同理完成治安和电力的数据交互,先治安
治安我们用飞线来完成
其实大致差不多,之前也封装过关于飞线的类,这里主要就是不断地位置变换
158.png

先new类出来
159.png

封装这边主要就是设置飞线顶点,从哪里到哪里,一般第一个0 0 0不变,然后最后一个就是落地的位置,中间一般介于两点之间的位置
160.png

161.gif

最后电力我们用雷达图来展示
在雷达图里面我们除了位置需要定义一个半径
162.png

这边封装,同样的给到position,同时雷达图需要定义一个半径
163.png

164.gif

十四.大屏HTML元素与场景物体数据交互与特效展现

也就是当我点击左右两边的2D面板对应的3D物体会做出一些处理,反之亦可
要实现这种操作,需要消息传送,可以时间总线也可以vuex等,这里用到一个插件
165.png

先封装出来一个可以直接用的bus总线
166.png

之前封装过一个每一个出来的图标点击绑定的有点击事件
167.png

168.png

通过点击3D把数据给到2D页面
169.png

2D页面接收
170.png

171.png

实现效果,点击3D页面对应2D列表为红色
172.png

173.png

174.gif

然后就是点击2D面板,相应的3D进行交互
绑定点击事件,通过插件传值
175.png

176.png

我们可以拿到点击的生成列表的下标,注意这里逻辑,在我们原来通过定时器生成雪碧图的时候,给每个物体添加一个index属性就是生成的顺序,然后这里通过点击事件拿到的顺序就可以让点击的显示,其他不显示
177.png

178.png

179.gif

如果要改对应的颜色,那就直接mesh的材质修改即可
接下来在做一个功能,当我点击2D面板,不仅显示这一个3D图,并且镜头要转向这个地方
180.png

181.gif


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册