|
@@ -0,0 +1,935 @@
|
|
|
|
+<!-- 模型地图 -->
|
|
|
|
+<template>
|
|
|
|
+ <div>
|
|
|
|
+ <div class="canvasMap" ref="container"></div>
|
|
|
|
+ </div>
|
|
|
|
+</template>
|
|
|
|
+
|
|
|
|
+<script>
|
|
|
|
+ import * as THREE from 'three';
|
|
|
|
+ import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
|
|
|
|
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
|
|
|
|
+ import TWEEN from 'tween.js';
|
|
|
|
+ import { CSS2DRenderer, CSS2DObject, } from "three/examples/jsm/renderers/CSS2DRenderer";
|
|
|
|
+ export default {
|
|
|
|
+ data() {
|
|
|
|
+ return {
|
|
|
|
+ boxWidth:2594,
|
|
|
|
+ // boxHeight:1320,
|
|
|
|
+ boxHeight:1240,
|
|
|
|
+ animationId: null, // 存储动画帧ID
|
|
|
|
+ model:null,
|
|
|
|
+ rotateType:true,
|
|
|
|
+ subModels: [],
|
|
|
|
+ houses:[],
|
|
|
|
+ textures: [], // 预加载的贴图选项
|
|
|
|
+ scene: null,
|
|
|
|
+ camera: null,
|
|
|
|
+ renderer: null,
|
|
|
|
+ controls: null,
|
|
|
|
+ labelRenderer:null,
|
|
|
|
+ // initialCameraPosition: new THREE.Vector3(0.265357272970017,1.0753467424793826,0.29965000584249346),//旋转-距离-俯角
|
|
|
|
+ initialCameraPosition: new THREE.Vector3(0.5,0.60,0.5),//旋转-距离-俯角
|
|
|
|
+ /*
|
|
|
|
+ {"x":0.2509298883560245,"y":1.2088432847403026,"z":0.19985043873282318}
|
|
|
|
+ {"x":0.265357272970017,"y":1.0753467424793826,"z":0.29965000584249346}
|
|
|
|
+ */
|
|
|
|
+ initialControlsTarget: new THREE.Vector3(0, 0, 0),
|
|
|
|
+ /*本地管理数据*/
|
|
|
|
+ modelBuildingList:[
|
|
|
|
+ {school:'B', name:'5号楼', buildId:'101093843117592833',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'6B教学楼', buildId:'101093843117592815',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'中心实验楼', buildId:'101093843117592829',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'信息工程学院教学楼', buildId:'101093843117592812',centerValue:'101093843117592812',valueList:['101093843117592812'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'养虫楼', buildId:'101093843117592805',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'农业机械实验室平房', buildId:'101093843117592807',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'农药研究所', buildId:'101093843117592804',centerValue:'101093843117592804',valueList:['101093843117592804'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'动物中心B座', buildId:'101093843117592785',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'动物中心实验楼A', buildId:'101093843117592765',centerValue:'101093843117592765',valueList:['101093843117592765'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'动物中心实验楼B', buildId:'101093843117592764',centerValue:'101093843117592764',valueList:['101093843117592764'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'动物科技学院楼', buildId:'101093843117592831',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'动科楼', buildId:'101093843117592832',centerValue:'101093843117592832',valueList:['101093843117592832'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'北1号教学楼', buildId:'101093843117592802',centerValue:'101093843117592802',valueList:['101093843117592802'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'北2号教学楼', buildId:'101093843117592813',centerValue:'101093843117592813',valueList:['101093843117592813'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'北3号教学楼', buildId:'101093843117592782',centerValue:'101093843117592782',valueList:['101093843117592782'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'北4号教学楼', buildId:'101093843117592781',centerValue:'101093843117592781',valueList:['101093843117592781'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'北5号教学楼', buildId:'101093843117592783',centerValue:'101093843117592833',valueList:['101093843117592833'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'北6号教学楼', buildId:'101093843117592814',centerValue:'101093843117592814',valueList:['101093843117592814'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'北7号教学楼', buildId:'101093843117592816',centerValue:'101093843117592816',valueList:['101093843117592816'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'危化品服务中心', buildId:'101093843117592826',centerValue:'101093843117592826-03',valueList:['101093843117592826-01','101093843117592826-02','101093843117592826-03','101093843117592826-04','101093843117592826-05'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'原农一站办公楼', buildId:'101093843117592811',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'工程训练中心楼', buildId:'101093843117592808',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'教学办公楼', buildId:'101093843117592806',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'未知实验室 ',buildId:'1855791848753147906',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'机械及液压实验室平房', buildId:'101093843117592810',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'机电锻铸车间', buildId:'101093843117592809',centerValue:'101093843117592809',valueList:['101093843117592809'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'水利与建筑工程学院', buildId:'101093843117592788',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'水利与建筑工程学院A', buildId:'101093843117592766',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'水利与建筑工程学院B', buildId:'101093843117592768',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'水利与建筑工程学院C', buildId:'101093843117592769',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'水利与建筑工程学院D', buildId:'101093843117592767',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'水工厅', buildId:'1871736666456633346',centerValue:'1871736666456633346',valueList:['1871736666456633346'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'水工水力学实验大厅', buildId:'1871729400227606529',centerValue:'1871729400227606529-01',valueList:['1871729400227606529-01','1871729400227606529-02'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'理科综合实验楼A', buildId:'101093843117592774',centerValue:'101093843117592774',valueList:['101093843117592774'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'理科综合实验楼B', buildId:'101093843117592779',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'理科综合实验楼C', buildId:'101093843117592775',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'理科综合实验楼D', buildId:'101093843117592776',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'理科综合实验楼E', buildId:'101093843117592780',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'老昆虫博物馆', buildId:'101093843117592786',centerValue:'101093843117592786',valueList:['101093843117592786'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'食品楼', buildId:'101093843117592789',centerValue:'101093843117592789',valueList:['101093843117592789'],alarmType:false,},
|
|
|
|
+ {school:'B', name:'食品楼A', buildId:'101093843117592771',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'食品楼B', buildId:'101093843117592770',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'食品楼C', buildId:'101093843117592772',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'B', name:'食品楼D', buildId:'101093843117592773',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'农科楼(农学院)', buildId:'101084081109864872',centerValue:'101084081109864872',valueList:['101084081109864872'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'农科楼(园艺学院)', buildId:'101084081109864874',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'农科楼(植物保护学院)', buildId:'101084081109864873',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'农科楼(资源环境学院)', buildId:'101093843117592803',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'农科院子校教学楼(初中)', buildId:'101093843117592823',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'南2号教学楼', buildId:'101093843117592817',centerValue:'101093843117592817',valueList:['101093843117592817'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'南3号教学楼', buildId:'101093843117592820',centerValue:'101093843117592820',valueList:['101093843117592820'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'南校子校楼', buildId:'101093843117592800',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'南校水保楼', buildId:'101093843117592801',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'家畜生物学重点实验室楼', buildId:'101093843117592787',centerValue:'101093843117592787',valueList:['101093843117592787'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'木艺坊', buildId:'101093843117592819',centerValue:'101093843117592819',valueList:['101093843117592819'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'林学院实验楼', buildId:'101093843117592818',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'科研主楼', buildId:'101093843117592784',centerValue:'101093843117592784',valueList:['101093843117592784'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'科研楼', buildId:'101093843117592822',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'经管园林楼(文科楼)A', buildId:'101093843117592777',centerValue:'101093843117592777',valueList:['101093843117592777'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'经管园林楼(文科楼)C', buildId:'101093843117592778',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'N', name:'草业与草原楼', buildId:'101093843117592825',centerValue:'101093843117592825',valueList:['101093843117592825'],alarmType:false,},
|
|
|
|
+ {school:'N', name:'林学院实验楼', buildId:'101093843117592821',centerValue:'101093843117592821',valueList:['101093843117592821'],alarmType:false,},
|
|
|
|
+ {school:'旱研院校区', name:'农一站科研楼', buildId:'101093843117592827',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'旱研院校区', name:'农机一站平房', buildId:'101093843117592828',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'校外', name:'农三站科研办公楼', buildId:'101093843117592790',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'校外', name:'器材楼', buildId:'101093843117592792',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'水保所校区', name:'人工降雨实验大厅', buildId:'101093843117592793',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'水保所校区', name:'南校区农科楼', buildId:'101093843117592799',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'水保所校区', name:'国家重点实验室西楼', buildId:'101093843117592798',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'水保所校区', name:'水保所人工干旱环境气候室工程', buildId:'101093843117592795',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'水保所校区', name:'水保所国家重点实验室楼', buildId:'101093843117592794',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'水保所校区', name:'水保所科研大楼', buildId:'101093843117592797',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'水保所校区', name:'水保所西区科研楼', buildId:'101093843117592796',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'老附中校区', name:'附中实验楼', buildId:'101093843117592830',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ {school:'老附中校区', name:'附中教学楼', buildId:'101093843117592791',centerValue:'',valueList:[],alarmType:false,},
|
|
|
|
+ ],
|
|
|
|
+ // 本地
|
|
|
|
+ modelsUrlN:'/models/NxiaoQu.glb',
|
|
|
|
+ modelsUrlB:'/models/BxiaoQu.glb',
|
|
|
|
+ alarmUrl:'/png/alarm.png',
|
|
|
|
+ noAlarmUrl:'/png/noAlarm.png',
|
|
|
|
+ // 本地部署
|
|
|
|
+ // modelsUrlN:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/models/NxiaoQu.glb':'/labAppTest/largeScreen/models/NxiaoQu.glb',
|
|
|
|
+ // modelsUrlB:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/models/BxiaoQu.glb':'/labAppTest/largeScreen/models/BxiaoQu.glb',
|
|
|
|
+ // alarmUrl:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/png/alarm.png':'/labAppTest/largeScreen/png/alarm.png',
|
|
|
|
+ // noAlarmUrl:this.judgmentNetworkReturnAddress()?'/v3/largeScreen/png/noAlarm.png':'/labAppTest/largeScreen/png/noAlarm.png',
|
|
|
|
+ // 线上部署
|
|
|
|
+ // modelsUrlN:'/largeScreen/models/NxiaoQu.glb',
|
|
|
|
+ // modelsUrlB:'/largeScreen/models/BxiaoQu.glb',
|
|
|
|
+ // alarmUrl:'/largeScreen/png/alarm.png',
|
|
|
|
+ // noAlarmUrl:'/largeScreen/png/noAlarm.png',
|
|
|
|
+ //当前校区状态
|
|
|
|
+ schoolType:'',
|
|
|
|
+ };
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ mounted() {
|
|
|
|
+ this.initThree();
|
|
|
|
+ this.loadModel('N');
|
|
|
|
+ this.loadAssets();
|
|
|
|
+ window.addEventListener('resize', this.onWindowResize);
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ beforeDestroy() {
|
|
|
|
+ // 停止动画循环
|
|
|
|
+ if (this.animationId) {
|
|
|
|
+ cancelAnimationFrame(this.animationId);
|
|
|
|
+ }
|
|
|
|
+ // 销毁Three.js相关资源
|
|
|
|
+ this.disposeThreeResources();
|
|
|
|
+ // 停止所有补间动画
|
|
|
|
+ TWEEN.removeAll();
|
|
|
|
+ // 移除事件监听器
|
|
|
|
+ window.removeEventListener('resize', this.onWindowResize);
|
|
|
|
+ this.renderer.dispose();
|
|
|
|
+ },
|
|
|
|
+
|
|
|
|
+ methods: {
|
|
|
|
+ //初始化
|
|
|
|
+ initThree() {
|
|
|
|
+ // 初始化场景
|
|
|
|
+ this.scene = new THREE.Scene();
|
|
|
|
+ //场景背景色
|
|
|
|
+ this.scene.background = new THREE.Color(0x000F14);
|
|
|
|
+ // 初始化渲染器
|
|
|
|
+ this.renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
|
|
+ // 主渲染器尺寸设置
|
|
|
|
+ this.renderer = new THREE.WebGLRenderer({ antialias: true });
|
|
|
|
+ this.renderer.setSize(this.boxWidth, this.boxHeight); // 固定尺寸
|
|
|
|
+ this.$refs.container.appendChild(this.renderer.domElement);
|
|
|
|
+ // 初始化相机时使用存储的位置
|
|
|
|
+ this.camera = new THREE.PerspectiveCamera(
|
|
|
|
+ 75,
|
|
|
|
+ // window.innerWidth / window.innerHeight,
|
|
|
|
+ this.boxWidth / this.boxHeight,
|
|
|
|
+ 0.1,
|
|
|
|
+ 1000
|
|
|
|
+ );
|
|
|
|
+ this.camera.position.copy(this.initialCameraPosition);
|
|
|
|
+
|
|
|
|
+ // 初始化控制器时存储初始目标
|
|
|
|
+ this.controls = new OrbitControls(this.camera, this.renderer.domElement);
|
|
|
|
+ this.controls.target.copy(this.initialControlsTarget);
|
|
|
|
+ this.labelRenderer = new CSS2DRenderer();
|
|
|
|
+ this.labelRenderer.setSize(this.boxWidth, this.boxHeight);
|
|
|
|
+ this.labelRenderer.domElement.style.position = 'absolute';
|
|
|
|
+ this.labelRenderer.domElement.style.top = '0';
|
|
|
|
+ this.labelRenderer.domElement.style.pointerEvents = 'none';//注释后 锁死鼠标视角
|
|
|
|
+ this.$refs.container.appendChild(this.labelRenderer.domElement);
|
|
|
|
+
|
|
|
|
+ // 初始化控制器
|
|
|
|
+ this.controls = new OrbitControls(this.camera, this.renderer.domElement);
|
|
|
|
+ this.controls.enableDamping = true;
|
|
|
|
+ this.controls.dampingFactor = 0.05;
|
|
|
|
+
|
|
|
|
+ // 添加灯光
|
|
|
|
+ const ambientLight = new THREE.AmbientLight(0xffffff, 1);
|
|
|
|
+ this.scene.add(ambientLight);
|
|
|
|
+
|
|
|
|
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
|
|
|
|
+ directionalLight.position.set(-1.5, 2, -1.5);
|
|
|
|
+ this.scene.add(directionalLight);
|
|
|
|
+
|
|
|
|
+ // 启动动画循环
|
|
|
|
+ this.animate();
|
|
|
|
+ },
|
|
|
|
+ //模型加载
|
|
|
|
+ loadModel(type) {
|
|
|
|
+ let self = this;
|
|
|
|
+ this.$set(this,'schoolType',type);
|
|
|
|
+ if(type == 'N'){
|
|
|
|
+ //南校区
|
|
|
|
+ const loaderN = new GLTFLoader();
|
|
|
|
+ loaderN.load(self.modelsUrlN, (gltf) => {
|
|
|
|
+ const model = gltf.scene;
|
|
|
|
+ this.model = gltf.scene;
|
|
|
|
+ this.scene.add(model);
|
|
|
|
+ // 递归查找所有Group
|
|
|
|
+ const traverseGroups = (obj) => {
|
|
|
|
+ if (obj.isGroup) {
|
|
|
|
+ this.registerHouse(obj);
|
|
|
|
+ }
|
|
|
|
+ obj.children.forEach(child => traverseGroups(child));
|
|
|
|
+ };
|
|
|
|
+ traverseGroups(gltf.scene);
|
|
|
|
+ // 获取所有子模型并计算中心点
|
|
|
|
+ model.traverse((child) => {
|
|
|
|
+ if (child.isGroup) {
|
|
|
|
+ const center = this.getBoundingBoxCenter(child);
|
|
|
|
+ this.subModels.push({
|
|
|
|
+ name: child.name,
|
|
|
|
+ center: center,
|
|
|
|
+ originalPosition: child.position.clone(),
|
|
|
|
+ mesh: child // 直接引用mesh对象 用于材质修改
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }else if(type == 'B'){
|
|
|
|
+ //北校区
|
|
|
|
+ const loaderB = new GLTFLoader();
|
|
|
|
+ loaderB.load(self.modelsUrlB, (gltf) => {
|
|
|
|
+ const model = gltf.scene;
|
|
|
|
+ this.model = gltf.scene;
|
|
|
|
+ this.scene.add(model);
|
|
|
|
+ // 递归查找所有Group
|
|
|
|
+ const traverseGroups = (obj) => {
|
|
|
|
+ if (obj.isGroup) {
|
|
|
|
+ this.registerHouse(obj);
|
|
|
|
+ }
|
|
|
|
+ obj.children.forEach(child => traverseGroups(child));
|
|
|
|
+ };
|
|
|
|
+ traverseGroups(gltf.scene);
|
|
|
|
+ // 获取所有子模型并计算中心点
|
|
|
|
+ model.traverse((child) => {
|
|
|
|
+ if (child.isGroup) {
|
|
|
|
+ const center = this.getBoundingBoxCenter(child);
|
|
|
|
+ this.subModels.push({
|
|
|
|
+ name: child.name,
|
|
|
|
+ center: center,
|
|
|
|
+ originalPosition: child.position.clone(),
|
|
|
|
+ mesh: child // 直接引用mesh对象 用于材质修改
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ setTimeout(function(){
|
|
|
|
+ self.buildingApplyTexture([]);
|
|
|
|
+ // self.buildingColor([]);
|
|
|
|
+ },500);
|
|
|
|
+ },
|
|
|
|
+ /****** 新模型相关方法-开始 *******/
|
|
|
|
+ // 修改后的 registerHouse 方法
|
|
|
|
+ registerHouse(group) {
|
|
|
|
+ const bbox = new THREE.Box3().setFromObject(group);
|
|
|
|
+ const center = bbox.getCenter(new THREE.Vector3());
|
|
|
|
+
|
|
|
|
+ // 记录原始材质
|
|
|
|
+ const originalMaterials = [];
|
|
|
|
+ group.traverse(child => {
|
|
|
|
+ if (child.isMesh) {
|
|
|
|
+ originalMaterials.push({
|
|
|
|
+ mesh: child,
|
|
|
|
+ material: child.material.clone() // 重要:必须克隆原始材质
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ this.houses.push({
|
|
|
|
+ name:group.name,
|
|
|
|
+ uuid: group.uuid,
|
|
|
|
+ group: group,
|
|
|
|
+ screenPosition: new THREE.Vector2(),
|
|
|
|
+ worldPosition: center,
|
|
|
|
+ originalMaterials: originalMaterials // 新增原始材质存储
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ // 预加载材质和贴图
|
|
|
|
+ loadAssets() {
|
|
|
|
+ const textureLoader = new THREE.TextureLoader();
|
|
|
|
+ this.textures = [
|
|
|
|
+ textureLoader.load(this.alarmUrl)
|
|
|
|
+ ];
|
|
|
|
+ },
|
|
|
|
+ // 报警样式
|
|
|
|
+ changeTexture(house) {
|
|
|
|
+ const texture = this.textures[Math.floor(Math.random() * this.textures.length)];
|
|
|
|
+ texture.needsUpdate = true;
|
|
|
|
+
|
|
|
|
+ house.group.traverse(child => {
|
|
|
|
+ if (child.isMesh) {
|
|
|
|
+ child.material.map = texture;
|
|
|
|
+ child.material.needsUpdate = true;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ // 恢复正常显示
|
|
|
|
+ restoreOriginalMaterial(house) {
|
|
|
|
+ house.originalMaterials.forEach(entry => {
|
|
|
|
+ entry.mesh.material.dispose(); // 清理当前材质
|
|
|
|
+ entry.mesh.material = entry.material.clone();
|
|
|
|
+ entry.mesh.material.needsUpdate = true;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ /****** 新模型相关方法-结束 *******/
|
|
|
|
+
|
|
|
|
+ getBoundingBoxCenter(obj) {
|
|
|
|
+ const box = new THREE.Box3().setFromObject(obj);
|
|
|
|
+ return box.getCenter(new THREE.Vector3());
|
|
|
|
+ },
|
|
|
|
+ onWindowResize() {
|
|
|
|
+ this.camera.aspect = this.boxWidth / this.boxHeight;
|
|
|
|
+ this.camera.updateProjectionMatrix();
|
|
|
|
+ this.renderer.setSize(this.boxWidth, this.boxHeight);
|
|
|
|
+ this.labelRenderer.setSize(this.boxWidth, this.boxHeight);
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
+ //动画刷新
|
|
|
|
+ animate() {
|
|
|
|
+ if (this.model&&this.rotateType) {
|
|
|
|
+ this.model.rotation.y += 0.001; // 添加简单旋转动画
|
|
|
|
+ }else if(this.model&&!this.rotateType){
|
|
|
|
+ this.model.rotation.y = 0;
|
|
|
|
+ }
|
|
|
|
+ // requestAnimationFrame(this.animate);
|
|
|
|
+ // TWEEN.update();
|
|
|
|
+ // this.controls.update();
|
|
|
|
+ // this.renderer.render(this.scene, this.camera);
|
|
|
|
+ // this.labelRenderer.render(this.scene, this.camera);
|
|
|
|
+ this.animationId = requestAnimationFrame(this.animate);
|
|
|
|
+ TWEEN.update();
|
|
|
|
+ this.controls.update();
|
|
|
|
+ this.renderer.render(this.scene, this.camera);
|
|
|
|
+ this.labelRenderer.render(this.scene, this.camera);
|
|
|
|
+ },
|
|
|
|
+ //预案关闭
|
|
|
|
+ alarmOff(){
|
|
|
|
+ let self = this;
|
|
|
|
+ self.$set(this,'rotateType',true)
|
|
|
|
+ if(this.schoolType == 'N'){
|
|
|
|
+ self.resetCamera();
|
|
|
|
+ self.del2dText();
|
|
|
|
+ // self.buildingColor([]);
|
|
|
|
+ self.buildingApplyTexture([]);
|
|
|
|
+ }else{
|
|
|
|
+ //删除所有文字
|
|
|
|
+ for(let i=0;i<self.scene.children.length;i++){
|
|
|
|
+ if(self.scene.children[i].isCSS2DObject){
|
|
|
|
+ self.scene.remove(self.scene.children[i]);
|
|
|
|
+ i--
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //删除模型数据
|
|
|
|
+ this.$set(this,'subModels',[]);
|
|
|
|
+ this.$set(this,'houses',[]);
|
|
|
|
+ this.scene.children.forEach((item)=>{
|
|
|
|
+ if(item.type == 'Group'){
|
|
|
|
+ this.scene.remove(item);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ self.resetCamera();
|
|
|
|
+ this.delLoadModel('N');
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ // 新增恢复视角方法
|
|
|
|
+ resetCamera() {
|
|
|
|
+ this.controls.enabled = false;
|
|
|
|
+ new TWEEN.Tween(this.camera.position)
|
|
|
|
+ .to(this.initialCameraPosition, 1500)
|
|
|
|
+ .easing(TWEEN.Easing.Quadratic.InOut)
|
|
|
|
+ .start();
|
|
|
|
+
|
|
|
|
+ new TWEEN.Tween(this.controls.target)
|
|
|
|
+ .to(this.initialControlsTarget, 1500)
|
|
|
|
+ .easing(TWEEN.Easing.Quadratic.InOut)
|
|
|
|
+ .onComplete(() => {
|
|
|
|
+ this.controls.enabled = true;
|
|
|
|
+ })
|
|
|
|
+ .start();
|
|
|
|
+ this.del2dText();
|
|
|
|
+ },
|
|
|
|
+ //删除所有2d文字
|
|
|
|
+ del2dText(){
|
|
|
|
+ let self = this;
|
|
|
|
+ for(let i=0;i<self.scene.children.length;i++){
|
|
|
|
+ if(self.scene.children[i].isCSS2DObject){
|
|
|
|
+ this.scene.remove(self.scene.children[i]);
|
|
|
|
+ i--
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ //预案触发
|
|
|
|
+ alarmTrigger(list,obj,type){
|
|
|
|
+ let self = this;
|
|
|
|
+ self.$set(this,'rotateType',false)
|
|
|
|
+ //list=所有报警数据 obj=需要聚焦的报警数据 type=报警的校区
|
|
|
|
+ if(this.schoolType == type){
|
|
|
|
+ //当前校区
|
|
|
|
+ self.buildingApplyTexture(list);
|
|
|
|
+ // self.buildingColor(list);
|
|
|
|
+ self.focusingLens(obj);
|
|
|
|
+ //删除所有文字
|
|
|
|
+ for(let i=0;i<self.scene.children.length;i++){
|
|
|
|
+ if(self.scene.children[i].isCSS2DObject){
|
|
|
|
+ self.scene.remove(self.scene.children[i]);
|
|
|
|
+ i--
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //生成新文字
|
|
|
|
+ this.alarmTextLabel(list);
|
|
|
|
+ }else{
|
|
|
|
+ //其他校区
|
|
|
|
+ //删除所有文字
|
|
|
|
+ for(let i=0;i<self.scene.children.length;i++){
|
|
|
|
+ if(self.scene.children[i].isCSS2DObject){
|
|
|
|
+ self.scene.remove(self.scene.children[i]);
|
|
|
|
+ i--
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ //删除模型数据
|
|
|
|
+ this.$set(this,'subModels',[]);
|
|
|
|
+ this.$set(this,'houses',[]);
|
|
|
|
+ this.scene.children.forEach((item)=>{
|
|
|
|
+ if(item.type == 'Group'){
|
|
|
|
+ self.scene.remove(item);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ //加载新模型
|
|
|
|
+ this.newLoadModel(list,obj,type);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ //新模型加载
|
|
|
|
+ newLoadModel(list,obj,type) {
|
|
|
|
+ let self = this;
|
|
|
|
+ this.$set(this,'schoolType',type);
|
|
|
|
+ if(type == 'N'){
|
|
|
|
+ //南校区
|
|
|
|
+ const loaderN = new GLTFLoader();
|
|
|
|
+ loaderN.load(self.modelsUrlN, (gltf) => {
|
|
|
|
+ const model = gltf.scene;
|
|
|
|
+ this.model = gltf.scene;
|
|
|
|
+ this.scene.add(model);
|
|
|
|
+ // 递归查找所有Group
|
|
|
|
+ const traverseGroups = (obj) => {
|
|
|
|
+ if (obj.isGroup) {
|
|
|
|
+ this.registerHouse(obj);
|
|
|
|
+ }
|
|
|
|
+ obj.children.forEach(child => traverseGroups(child));
|
|
|
|
+ };
|
|
|
|
+ traverseGroups(gltf.scene);
|
|
|
|
+ // 获取所有子模型并计算中心点
|
|
|
|
+ model.traverse((child) => {
|
|
|
|
+ if (child.isGroup) {
|
|
|
|
+ const center = this.getBoundingBoxCenter(child);
|
|
|
|
+ this.subModels.push({
|
|
|
|
+ name: child.name,
|
|
|
|
+ center: center,
|
|
|
|
+ originalPosition: child.position.clone(),
|
|
|
|
+ mesh: child // 直接引用mesh对象 用于材质修改
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }else if(type == 'B'){
|
|
|
|
+ //北校区
|
|
|
|
+ const loaderB = new GLTFLoader();
|
|
|
|
+ loaderB.load(self.modelsUrlB, (gltf) => {
|
|
|
|
+ const model = gltf.scene;
|
|
|
|
+ this.model = gltf.scene;
|
|
|
|
+ this.scene.add(model);
|
|
|
|
+ // 递归查找所有Group
|
|
|
|
+ const traverseGroups = (obj) => {
|
|
|
|
+ if (obj.isGroup) {
|
|
|
|
+ this.registerHouse(obj);
|
|
|
|
+ }
|
|
|
|
+ obj.children.forEach(child => traverseGroups(child));
|
|
|
|
+ };
|
|
|
|
+ traverseGroups(gltf.scene);
|
|
|
|
+ // 获取所有子模型并计算中心点
|
|
|
|
+ model.traverse((child) => {
|
|
|
|
+ if (child.isGroup) {
|
|
|
|
+ const center = this.getBoundingBoxCenter(child);
|
|
|
|
+ this.subModels.push({
|
|
|
|
+ name: child.name,
|
|
|
|
+ center: center,
|
|
|
|
+ originalPosition: child.position.clone(),
|
|
|
|
+ mesh: child // 直接引用mesh对象 用于材质修改
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ setTimeout(function(){
|
|
|
|
+ self.focusingLens(obj);
|
|
|
|
+ self.buildingApplyTexture(list);
|
|
|
|
+ // self.buildingColor(list);
|
|
|
|
+ self.alarmTextLabel(list);
|
|
|
|
+ },1500);
|
|
|
|
+ },
|
|
|
|
+ //预案停止模型加载
|
|
|
|
+ delLoadModel(type) {
|
|
|
|
+ let self = this;
|
|
|
|
+ this.$set(this,'schoolType',type);
|
|
|
|
+ //南校区
|
|
|
|
+ const loaderN = new GLTFLoader();
|
|
|
|
+ loaderN.load(self.modelsUrlN, (gltf) => {
|
|
|
|
+ const model = gltf.scene;
|
|
|
|
+ this.model = gltf.scene;
|
|
|
|
+ this.scene.add(model);
|
|
|
|
+ // 递归查找所有Group
|
|
|
|
+ const traverseGroups = (obj) => {
|
|
|
|
+ if (obj.isGroup) {
|
|
|
|
+ this.registerHouse(obj);
|
|
|
|
+ }
|
|
|
|
+ obj.children.forEach(child => traverseGroups(child));
|
|
|
|
+ };
|
|
|
|
+ traverseGroups(gltf.scene);
|
|
|
|
+ // 获取所有子模型并计算中心点
|
|
|
|
+ model.traverse((child) => {
|
|
|
|
+ if (child.isGroup) {
|
|
|
|
+ const center = this.getBoundingBoxCenter(child);
|
|
|
|
+ this.subModels.push({
|
|
|
|
+ name: child.name,
|
|
|
|
+ center: center,
|
|
|
|
+ originalPosition: child.position.clone(),
|
|
|
|
+ mesh: child // 直接引用mesh对象 用于材质修改
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ });
|
|
|
|
+ setTimeout(function(){
|
|
|
|
+ self.buildingApplyTexture([]);
|
|
|
|
+ // self.buildingColor([]);
|
|
|
|
+ },1500);
|
|
|
|
+ },
|
|
|
|
+ //初始化楼栋标记(报警时调用)
|
|
|
|
+ buildingColor(list){
|
|
|
|
+ let self = this;
|
|
|
|
+ //处理基础数据
|
|
|
|
+ self.modelBuildingList.forEach((maxItem)=>{
|
|
|
|
+ let num = 0;
|
|
|
|
+ list.forEach((item)=>{
|
|
|
|
+ if(maxItem.buildId == item.buildId){
|
|
|
|
+ num++
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ maxItem.alarmType = num != 0;
|
|
|
|
+ })
|
|
|
|
+ //处理预警与正常贴图
|
|
|
|
+ self.modelBuildingList.forEach((maxItem)=>{
|
|
|
|
+ maxItem.valueList.forEach((bigItem)=>{
|
|
|
|
+ this.scene.children.forEach((item)=>{
|
|
|
|
+ if(item.type == 'Group'){
|
|
|
|
+ item.children.forEach((minItem)=>{
|
|
|
|
+ if(minItem.name == bigItem){
|
|
|
|
+ if(maxItem.alarmType){
|
|
|
|
+ self.applyTexture(self.alarmUrl,minItem);
|
|
|
|
+ }else{
|
|
|
|
+ self.applyTexture(self.noAlarmUrl,minItem);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ buildingApplyTexture(list){
|
|
|
|
+ let self = this;
|
|
|
|
+ //处理基础数据
|
|
|
|
+ self.modelBuildingList.forEach((maxItem)=>{
|
|
|
|
+ let num = 0;
|
|
|
|
+ list.forEach((item)=>{
|
|
|
|
+ if(maxItem.buildId == item.buildId){
|
|
|
|
+ num++
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ maxItem.alarmType = num != 0;
|
|
|
|
+ })
|
|
|
|
+ this.$forceUpdate()
|
|
|
|
+ //处理预警与正常贴图
|
|
|
|
+ self.modelBuildingList.forEach((maxItem)=>{
|
|
|
|
+ maxItem.valueList.forEach((bigItem)=>{
|
|
|
|
+ self.houses.forEach((minItem)=>{
|
|
|
|
+ if(minItem.name == bigItem){
|
|
|
|
+ if(maxItem.alarmType){
|
|
|
|
+ self.changeTexture(minItem);
|
|
|
|
+ }else{
|
|
|
|
+ self.restoreOriginalMaterial(minItem);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ //图片材质替换
|
|
|
|
+ applyTexture(textureName,obj) {
|
|
|
|
+ const textureLoader = new THREE.TextureLoader();
|
|
|
|
+ textureLoader.load(
|
|
|
|
+ textureName, // 图片放在public目录下
|
|
|
|
+ (texture) => {
|
|
|
|
+ texture.flipY = false; // 根据图片格式调整
|
|
|
|
+ obj.traverse((child) => {
|
|
|
|
+ if (child.isMesh) {
|
|
|
|
+ // 释放旧纹理资源
|
|
|
|
+ if (child.material.map) {
|
|
|
|
+ child.material.map.dispose();
|
|
|
|
+ }
|
|
|
|
+ child.material.map = texture;
|
|
|
|
+ child.material.needsUpdate = true;
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ undefined,
|
|
|
|
+ (error) => {
|
|
|
|
+ console.error('材质加载失败:', error);
|
|
|
|
+ }
|
|
|
|
+ );
|
|
|
|
+ },
|
|
|
|
+ //材质方法调用
|
|
|
|
+ changeMaterial(options) {
|
|
|
|
+ const {
|
|
|
|
+ modelSelector, // 支持三种选择方式:名称(name)/索引(index)/'all'
|
|
|
|
+ materialParams, // 新材质参数对象
|
|
|
|
+ keepOriginal = false // 是否保留原始材质
|
|
|
|
+ } = options;
|
|
|
|
+
|
|
|
|
+ const targetMeshes = this.getTargetMeshes(modelSelector);
|
|
|
|
+
|
|
|
|
+ targetMeshes.forEach(mesh => {
|
|
|
|
+ // 创建新材质
|
|
|
|
+ const newMaterial = this.createMaterial(materialParams);
|
|
|
|
+
|
|
|
|
+ // 处理旧材质
|
|
|
|
+ if (!keepOriginal && mesh.userData.originalMaterial) {
|
|
|
|
+ mesh.material.dispose();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 应用新材质
|
|
|
|
+ mesh.material = newMaterial;
|
|
|
|
+ });
|
|
|
|
+ },
|
|
|
|
+ // 辅助方法:获取目标网格
|
|
|
|
+ getTargetMeshes(selector) {
|
|
|
|
+ if (selector === 'all') {
|
|
|
|
+ return this.subModels.map(m => m.mesh);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (typeof selector === 'number') {
|
|
|
|
+ return [this.subModels[selector].mesh];
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (typeof selector === 'string') {
|
|
|
|
+ return this.subModels
|
|
|
|
+ .filter(m => m.name === selector)
|
|
|
|
+ .map(m => m.mesh);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return [];
|
|
|
|
+ },
|
|
|
|
+ // 材质工厂方法
|
|
|
|
+ createMaterial(params) {
|
|
|
|
+ const type = params.type || 'Standard';
|
|
|
|
+ const baseParams = {
|
|
|
|
+ color: new THREE.Color(params.color || 0xffffff),
|
|
|
|
+ map: params.texture ? this.loadTexture(params.texture) : null,
|
|
|
|
+ transparent: params.transparent || false,
|
|
|
|
+ opacity: params.opacity || 1.0,
|
|
|
|
+ ...params
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ switch(type.toLowerCase()) {
|
|
|
|
+ case 'basic':
|
|
|
|
+ return new THREE.MeshBasicMaterial(baseParams);
|
|
|
|
+ case 'phong':
|
|
|
|
+ return new THREE.MeshPhongMaterial(baseParams);
|
|
|
|
+ case 'standard':
|
|
|
|
+ return new THREE.MeshStandardMaterial(baseParams);
|
|
|
|
+ case 'physical':
|
|
|
|
+ return new THREE.MeshPhysicalMaterial(baseParams);
|
|
|
|
+ default:
|
|
|
|
+ return new THREE.MeshStandardMaterial(baseParams);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ //聚焦镜头查询
|
|
|
|
+ focusingLens(obj){
|
|
|
|
+ let self = this;
|
|
|
|
+ this.modelBuildingList.forEach((maxItem)=>{
|
|
|
|
+ if(maxItem.buildId == obj.buildId){
|
|
|
|
+ self.subModels.forEach((bigItem)=>{
|
|
|
|
+ if(bigItem.name == maxItem.centerValue){
|
|
|
|
+ self.moveCameraToModel(bigItem,bigItem.name);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ },
|
|
|
|
+ //镜头聚焦方法
|
|
|
|
+ moveCameraToModel(model,name) {
|
|
|
|
+ let self = this;
|
|
|
|
+ // 禁用控制器
|
|
|
|
+ this.controls.enabled = false;
|
|
|
|
+
|
|
|
|
+ // 计算目标位置(模型中心前上方)
|
|
|
|
+ const targetPosition = new THREE.Vector3()
|
|
|
|
+ .copy(model.center)
|
|
|
|
+ .add(new THREE.Vector3(0.2,0.2, 0.2));
|
|
|
|
+
|
|
|
|
+ // 动画参数
|
|
|
|
+ const duration = 1500;
|
|
|
|
+ const easing = TWEEN.Easing.Quadratic.InOut;
|
|
|
|
+
|
|
|
|
+ // 相机位置动画
|
|
|
|
+ new TWEEN.Tween(this.camera.position)
|
|
|
|
+ .to(targetPosition, duration)
|
|
|
|
+ .easing(easing)
|
|
|
|
+ .start();
|
|
|
|
+
|
|
|
|
+ // 控制器目标点动画
|
|
|
|
+ new TWEEN.Tween(this.controls.target)
|
|
|
|
+ .to(model.center, duration)
|
|
|
|
+ .easing(easing)
|
|
|
|
+ .onComplete(() => {
|
|
|
|
+ this.controls.enabled = true; // 恢复控制
|
|
|
|
+ })
|
|
|
|
+ .start();
|
|
|
|
+ },
|
|
|
|
+ //预警文本生成
|
|
|
|
+ alarmTextLabel(list){
|
|
|
|
+ let self = this;
|
|
|
|
+ let newList = [];
|
|
|
|
+ self.modelBuildingList.forEach((maxItem)=>{
|
|
|
|
+ list.forEach((item)=>{
|
|
|
|
+ if(maxItem.buildId == item.buildId){
|
|
|
|
+ let num = 0;
|
|
|
|
+ newList.forEach((minItem)=>{
|
|
|
|
+ if(minItem.buildId == item.buildId){
|
|
|
|
+ num++
|
|
|
|
+ if(!minItem.textList[1]){
|
|
|
|
+ minItem.textList.push(
|
|
|
|
+ "<div style='border-top:1px dashed #E90104;margin-top:15px;'>" +
|
|
|
|
+ "<p style='color:#FF8400;font-size:24px;line-height:30px;margin-top:19px;'>"+item.riskPlanName+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+this.parseTime(item.eventStartTime,"{y}-{m}-{d} {h}:{i}:{s}")+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+item.floorName+"-"+item.roomNum+"-"+item.deptName+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'><span style='border:1px solid "+item.classLevelColor+";padding:0 10px;margin-right:20px;border-radius:20px;color:"+item.classLevelColor+";'>"+item.classLevelName+"</span>"+item.subName+"</p>"+
|
|
|
|
+ "</div>"
|
|
|
|
+ )
|
|
|
|
+ }else{
|
|
|
|
+ minItem.textList.splice(0,1)
|
|
|
|
+ minItem.textList.push(
|
|
|
|
+ "<div style='border-top:1px dashed #E90104;margin-top:35px;'>" +
|
|
|
|
+ "<p style='color:#FF8400;font-size:24px;line-height:30px;margin-top:19px;'>"+item.riskPlanName+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+this.parseTime(item.eventStartTime,"{y}-{m}-{d} {h}:{i}:{s}")+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+item.floorName+"-"+item.roomNum+"-"+item.deptName+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'><span style='border:1px solid "+item.classLevelColor+";padding:0 10px;margin-right:20px;border-radius:20px;color:"+item.classLevelColor+";'>"+item.classLevelName+"</span>"+item.subName+"</p>"+
|
|
|
|
+ "</div>"
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ if(num == 0){
|
|
|
|
+ newList.push(
|
|
|
|
+ {
|
|
|
|
+ buildId:item.buildId,
|
|
|
|
+ centerValue:maxItem.centerValue,
|
|
|
|
+ text:"",
|
|
|
|
+ //校区-楼栋
|
|
|
|
+ titleName:item.schoolName+' - '+item.buildName,
|
|
|
|
+ textList:[
|
|
|
|
+ "<div>" +
|
|
|
|
+ "<p style='color:#FF8400;font-size:24px;line-height:30px;margin-top:19px;'>"+item.riskPlanName+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+this.parseTime(item.eventStartTime,"{y}-{m}-{d} {h}:{i}:{s}")+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'>"+item.floorName+"-"+item.roomNum+"-"+item.deptName+"</p>"+
|
|
|
|
+ "<p style='font-size:24px;line-height:30px;margin-top:5px;'><span style='border:1px solid "+item.classLevelColor+";padding:0 10px;margin-right:20px;border-radius:20px;color:"+item.classLevelColor+";'>"+item.classLevelName+"</span>"+item.subName+"</p>"+
|
|
|
|
+ "</div>"
|
|
|
|
+ ]
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ //循环定位模型位置并生成textTable
|
|
|
|
+ newList.forEach((maxItem,maxIndex)=>{
|
|
|
|
+ maxItem.text = "<div style='z-index:"+maxIndex+";border-radius:20px;padding:20px;color:#ffffff;border:1px solid #E90104;box-shadow: inset 0 0 10px rgba(176, 0, 0, 1);background-color: rgba(187,0,0,0.5)'>"
|
|
|
|
+ maxItem.text = maxItem.text+"<p style='border-bottom:1px solid #E90104;line-height:30px;padding-bottom:15px;'>"+maxItem.titleName+"</p>";
|
|
|
|
+ maxItem.textList.forEach((html)=>{
|
|
|
|
+ maxItem.text = maxItem.text + html
|
|
|
|
+ })
|
|
|
|
+ maxItem.text = maxItem.text+"</div>"
|
|
|
|
+ self.subModels.forEach((bigItem)=>{
|
|
|
|
+ if(bigItem.name == maxItem.centerValue){
|
|
|
|
+ forScene(bigItem,maxItem.text);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ })
|
|
|
|
+ function forScene(model,text){
|
|
|
|
+ self.scene.children.forEach((item)=>{
|
|
|
|
+ if(item.type == 'Group'){
|
|
|
|
+ item.children.forEach((minItem)=>{
|
|
|
|
+ if(minItem.name == model.name){
|
|
|
|
+ self.add2dFont(minItem,model.center,text);
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ //生成css2d文字
|
|
|
|
+ add2dFont(model,center,text){
|
|
|
|
+ const labelDiv = document.createElement('div');
|
|
|
|
+ labelDiv.style.fontSize = '24px';
|
|
|
|
+ labelDiv.style.width = '560px';
|
|
|
|
+ labelDiv.style.borderRadius = '10px';
|
|
|
|
+ labelDiv.style.whiteSpace = "pre-line";
|
|
|
|
+ labelDiv.innerHTML = text;
|
|
|
|
+
|
|
|
|
+ // 创建 CSS2D 对象并绑定到目标
|
|
|
|
+ const label = new CSS2DObject(labelDiv);
|
|
|
|
+ const targetPosition = new THREE.Vector3()
|
|
|
|
+ .copy(center)
|
|
|
|
+ .add(new THREE.Vector3(0.09,0.08,-0.1));
|
|
|
|
+ label.position.set(targetPosition.x,targetPosition.y,targetPosition.z); // 在对象上方 1 单位位置
|
|
|
|
+ this.scene.add(label);
|
|
|
|
+ },
|
|
|
|
+ //内外网地址判定
|
|
|
|
+ judgmentNetworkReturnAddress() {
|
|
|
|
+ /*判断是否是内网IP*/
|
|
|
|
+ // 获取当前页面url
|
|
|
|
+ var curPageUrl = window.location.href;
|
|
|
|
+
|
|
|
|
+ var reg1 = /(http|ftp|https|www):\/\//g;//去掉前缀
|
|
|
|
+ curPageUrl =curPageUrl.replace(reg1,'');
|
|
|
|
+
|
|
|
|
+ var reg2 = /\:+/g;//替换冒号为一点
|
|
|
|
+ curPageUrl =curPageUrl.replace(reg2,'.');
|
|
|
|
+
|
|
|
|
+ curPageUrl = curPageUrl.split('.');//通过一点来划分数组
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ var ipAddress = curPageUrl[0]+'.'+curPageUrl[1]+'.'+curPageUrl[2]+'.'+curPageUrl[3];
|
|
|
|
+
|
|
|
|
+ var isInnerIp = false;//默认给定IP不是内网IP
|
|
|
|
+ var ipNum = getIpNum(ipAddress);
|
|
|
|
+ /**
|
|
|
|
+ * 私有IP:A类 10.0.0.0 -10.255.255.255
|
|
|
|
+ * B类 172.16.0.0 -172.31.255.255
|
|
|
|
+ * C类 192.168.0.0 -192.168.255.255
|
|
|
|
+ * D类 127.0.0.0 -127.255.255.255(环回地址)
|
|
|
|
+ **/
|
|
|
|
+ var aBegin = getIpNum("10.0.0.0");
|
|
|
|
+ var aEnd = getIpNum("10.255.255.255");
|
|
|
|
+ var bBegin = getIpNum("172.16.0.0");
|
|
|
|
+ var bEnd = getIpNum("172.31.255.255");
|
|
|
|
+ var cBegin = getIpNum("192.168.0.0");
|
|
|
|
+ var cEnd = getIpNum("192.168.255.255");
|
|
|
|
+ var dBegin = getIpNum("127.0.0.0");
|
|
|
|
+ var dEnd = getIpNum("127.255.255.255");
|
|
|
|
+ isInnerIp = isInner(ipNum,aBegin,aEnd) || isInner(ipNum,bBegin,bEnd) || isInner(ipNum,cBegin,cEnd) || isInner(ipNum,dBegin,dEnd);
|
|
|
|
+ return isInnerIp?true:false;
|
|
|
|
+ /*获取IP数*/
|
|
|
|
+ function getIpNum(ipAddress) {
|
|
|
|
+ var ip = ipAddress.split(".");
|
|
|
|
+ var a = parseInt(ip[0]);
|
|
|
|
+ var b = parseInt(ip[1]);
|
|
|
|
+ var c = parseInt(ip[2]);
|
|
|
|
+ var d = parseInt(ip[3]);
|
|
|
|
+ var ipNum = a * 256 * 256 * 256 + b * 256 * 256 + c * 256 + d;
|
|
|
|
+ return ipNum;
|
|
|
|
+ }
|
|
|
|
+ function isInner(userIp,begin,end){
|
|
|
|
+ return (userIp>=begin) && (userIp<=end);
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ // 资源销毁方法
|
|
|
|
+ disposeThreeResources() {
|
|
|
|
+ // 释放几何体和材质
|
|
|
|
+ this.scene.traverse(child => {
|
|
|
|
+ if (child.isMesh) {
|
|
|
|
+ child.geometry.dispose();
|
|
|
|
+ if (Array.isArray(child.material)) {
|
|
|
|
+ child.material.forEach(m => m.dispose());
|
|
|
|
+ } else {
|
|
|
|
+ child.material.dispose();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+
|
|
|
|
+ // 释放渲染器
|
|
|
|
+ this.renderer.dispose();
|
|
|
|
+ this.labelRenderer.domElement.remove();
|
|
|
|
+ this.labelRenderer = null;
|
|
|
|
+
|
|
|
|
+ // 释放场景和相机
|
|
|
|
+ this.scene = null;
|
|
|
|
+ this.camera = null;
|
|
|
|
+
|
|
|
|
+ // 释放控制器
|
|
|
|
+ this.controls.dispose();
|
|
|
|
+ this.controls = null;
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+</script>
|
|
|
|
+<style scoped lang="scss">
|
|
|
|
+ .canvasMap{
|
|
|
|
+ position: absolute;
|
|
|
|
+ /*top: 122px;*/
|
|
|
|
+ top: 202px;
|
|
|
|
+ left: 64px;
|
|
|
|
+ width: 100%;
|
|
|
|
+ height: 100%;
|
|
|
|
+ }
|
|
|
|
+</style>
|