前言 趁着双休日和大家一起来学习一下智慧城市是怎么基本实现的,和大家一起学习,努力做大做强。
Vue创建智慧城市项目并配置glsl写法支持 创建项目 根据npm版本创建vite项目,如果没有vite或者想了解更多可以前往vite官网 查看
查看npm版本 创建项目 1 npm create vite@latest threeapp -- --template vue 
打开项目并安装依赖运行 
配置glsl写法支持 新建测试的glsl文件 在src目录下新建一个shader文件夹,然后新建一个test文件夹,再创建Vertex.glsl的顶点着色器文件
配置vite支持@符号 
1 2 3 4 5 6 7 import  { resolve } from  'path' resolve : {        alias : {             "@" : resolve (__dirname, 'src' ),          },         extensions : ['.js' , '.json' , '.glsl' ]      } 
在helloword中导入glsl文件 1 2 import  testVertex from  "@/shader/test/Vertex.glsl" ;console .log (testVertex);
让vite识别字符串文件 那该如何解决呢,其实很简单,我们只需要告诉vite,我们导入的字符串就行了,导入文件后缀名加上raw
1 import  testVertex from  "@/shader/test/Vertex.glsl?raw" ;
拓展webpack配置 这里我们拓展一下,如果是使用webpack脚手架,让支持glsl文件,那么就稍微比较麻烦了,配置如下
1 npm i webpack-glsl-loader --save -dev  
接下来在vue.config.js中配置
1 2 3 4 5 6 7 8 9 10 configureWebpack :(config )=>  {    config.module .rules .push ({         text :/\.glsl$/ ,         use :[                 {                     loader :'webpack-glsl-loader'                  }             ]     }) } 
ok,这样我们就可以在vue项目中使用glsl文件了
下面开始我们的项目基础代码结构分解,我们写代码的,不能把所有代码都写到一个组件里面去,这样上拉下拉太累了,所以要学会封装
项目基础代码结构分解 基础配置 安装three和gsap 1 2 npm install three npm install gsap 
在package.json中可以看到three就是安装成功了
设置全局样式 清除style.css中原有样式,设置margin,padding都为0
创建一个场景组件Scene.vue,并配置基础代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 <template>     <div class="scene" ref="sceneDiv">              </div> </template> <script setup> import {onMounted,ref} from 'vue'; import * as THREE from 'three'; // 导入轨道控制器 import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; // 场景元素div let sceneDiv = ref(null); // 1.创建场景 const scene = new THREE.Scene() // 2.创建相机 const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000) // 设置相机位置 camera.position.set(0, 0, 10) // 添加相机 scene.add(camera) // 初始化渲染器 const renderer = new THREE.WebGLRenderer(); //设置渲染的尺寸大小 renderer.setSize(window.innerWidth, window.innerHeight); //当前是平面的,让平面立体起来,使用控制器controls // 创建轨道控制器 const controls = new OrbitControls(camera, renderer.domElement); controls.enableDamping=true // 添加坐标轴辅助器 const axesHelper = new THREE.AxesHelper(5); scene.add(axesHelper) // 监听画面的变化,更新渲染的画面 window.addEventListener("resize", () => {     // console.log("画面变化了")     // 更新摄像头     camera.aspect = window.innerWidth / window.innerHeight;     // 更新摄像机的投影矩阵     camera.updateProjectionMatrix();     // 更新渲染器     renderer.setSize(window.innerWidth, window.innerHeight);     // 设置渲染器的像素比     renderer.setPixelRatio(window.devicePixelRatio) }) onMounted(()=>{     // 将webgl渲染的canvas内容添加到body上     sceneDiv.value.appendChild(renderer.domElement);     animate(); }) function animate() {     controls.update()     requestAnimationFrame(animate);     // 使用渲染器渲染相机看这个场景的内容渲染出来     renderer.render(scene, camera); } </script> <style> .scene{     width: 100vw;     height: 100vh;     position: fixed;     z-index:100;     left:0;     top:0; } </style> 
在App.vue中导入Scene.vue 
拆分代码 接下来我们把代码拆分出去,让我们的主函数组件更加的简洁
1 2 3 4 5 6 7 8 9 10 11 12 13 import  camera from  "./camera" ;import  renderer from  "./renderer" ;import  controls from  "./controls" ;import  scene from  "./scene" ;function  animate (  controls.update ();   requestAnimationFrame (animate);      renderer.render (scene, camera); } export  default  animate;
1 2 3 4 5 import  * as  THREE  from  "three" ;const  axesHelper = new  THREE .AxesHelper (5 );export  default  axesHelper;
1 2 3 4 5 6 7 8 9 import  * as  THREE  from  'three' ;const  camera = new  THREE .PerspectiveCamera (75 , window .innerWidth  / window .innerHeight , 0.1 , 1000 )camera.position .set (0 , 0 , 10 ) export  default  camera;
1 2 3 4 5 6 7 8 9 10 11 12 13 import  { OrbitControls  } from  "three/examples/jsm/controls/OrbitControls" ;import  camera from  "./camera" ;import  renderer from  "./renderer" ;const  controls = new  OrbitControls (camera, renderer.domElement );controls.enableDamping  = true ; export  default  controls;
1 2 3 export  default  function  createMesh (    console .log ("111" ) } 
1 2 3 4 5 6 7 import  { GUI  } from  "three/examples/jsm/libs/lil-gui.module.min.js" ;const  gui = new  GUI ();export  default  gui;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import  camera from  "./camera" ;import  renderer from  "./renderer" ;camera.aspect  = window .innerWidth  / window .innerHeight ; camera.updateProjectionMatrix (); window .addEventListener ("resize" , () =>  {        camera.aspect  = window .innerWidth  / window .innerHeight ;      camera.updateProjectionMatrix ();      renderer.setSize (window .innerWidth , window .innerHeight );      renderer.setPixelRatio (window .devicePixelRatio ); }); 
1 2 3 4 5 6 7 8 9 10 11 import  * as  THREE  from  'three' ;const  renderer = new  THREE .WebGLRenderer ();renderer.setSize (window .innerWidth , window .innerHeight ); renderer.shadowMap .enabled  = true ; export  default  renderer;
1 2 3 4 5 6 import  * as  THREE  from  'three' ;const  scene = new  THREE .Scene ();export  default  scene;
然后在scene.vue中导入这些文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 <template>     <div class="scene" ref="sceneDiv">              </div> </template> <script setup> import {onMounted,ref} from 'vue'; import * as THREE from 'three'; // 导入场景 import scene from "@/three/scene" // 导入相机 import camera from "@/three/camera" // 导入gui对象 import gui from "@/three/gui" // 导入renderer对象 import renderer from "@/three/renderer" // 导入辅助坐标轴 import axesHelper from "@/three/axesHelper"; // 导入控制器 import controls from "@/three/controls"; // 导入每一帧的执行函数 import animate from "@/three/animate"; // 初始化调整屏幕 import "@/three/init"; // 导入创建物体函数 import createMesh from "@/three/createMesh"; // 场景元素div let sceneDiv = ref(null); // 添加相机 scene.add(camera) // 添加辅助坐标轴 scene.add(axesHelper); createMesh(); onMounted(()=>{     // 将webgl渲染的canvas内容添加到body上     sceneDiv.value.appendChild(renderer.domElement);     animate(); }) </script> <style> .scene{     width: 100vw;     height: 100vh;     position: fixed;     z-index:100;     left:0;     top:0; } </style> 
我们可以看到,代码依旧是正常可以执行的