webgl_rxdz_look.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. <template src="./webgl_rxdz_look.html">
  2. </template>
  3. <script>
  4. import * as THREE from 'three';
  5. import Stats from 'three/addons/libs/stats.module.js';
  6. import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
  7. import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
  8. import spaceTypes from '@/static/spaceTypesIE.js';
  9. import TWEEN from 'three/addons/libs/tween.module.js';
  10. var requestId = "";
  11. const util = require('@/utils/util.js');
  12. const config = require('@/services/urlConfig.js');
  13. import loadModel from '@/mixins/loadModel.js';
  14. import wallMethod from '@/mixins/wallMethod.js';
  15. import floorMethod from '@/mixins/floorMethod.js';
  16. import commonPageMethod from '@/mixins/commonPageMethod.js';
  17. // const app = getApp(); //获取应用实例
  18. export default {
  19. mixins:[loadModel,floorMethod,wallMethod,commonPageMethod],
  20. /**
  21. * 页面的初始数据
  22. */
  23. data() {
  24. return {
  25. pvCurPageName: "webgl_rxdz_look",
  26. pvCurPageParams: null,
  27. locusBehaviorName: "查看页面",
  28. houseId: "",
  29. pvId: 'p_2cmina_23080404',
  30. navbar: {
  31. showCapsule: 1,
  32. title: '查看户型',
  33. titleColor: '#fff',
  34. navPadding: 0,
  35. navPaddingBg:'transparent',
  36. navBarColor: 'transparent',
  37. navBackColor: 'transparent',
  38. haveCallback: true, // 如果是 true 会接手 navbarBackClk
  39. fromShare: false,
  40. fromProject: 0,
  41. shareToken: "",
  42. pageName: this.pvCurPageName,
  43. },
  44. canvas:null,
  45. id:'',// 户型编号
  46. spaceList:[], // 空间列表
  47. gltfSpaces:[], // 场景中地板模型数组
  48. spaceId:null,
  49. wallIds:[], // 空间墙体id
  50. wallList:[], // 墙体数据
  51. gltfWalls:[], // 场景中墙体模型数组
  52. loader:null,
  53. scene:null,
  54. // sky:null,
  55. camera:null,
  56. controls:null,
  57. curHouseObj: null,
  58. controlStarPosition : { x:0, y:0, z:0}, //控制器初始位置
  59. cameraStarPosition : { x:0, y:20, z:0} ,//摄像头初始位置
  60. // cameraLastPosition: null, //摄像头上一次移动到的位置
  61. // controlLastPosition: null, //观察点上一次移动到的位置
  62. canvasHeight:430, //canvas视图的高度-计算得出
  63. chooseMesh:null,//标记鼠标拾取到的mesh
  64. progress:1, //进度条
  65. myLoadingStatus:false,
  66. repeatFlag:false, //重复点击
  67. instancedFloorMesh:null,
  68. instancedMeshList: [],
  69. lableItem:[],
  70. showLables:false,
  71. gltfSpaceRoofs:[], // 屋顶模型数组
  72. floorList:[],
  73. floorId:null,
  74. curData:null, //上一个页面传来的数据
  75. curSpaceObj:null, //当前应该定位到的空间
  76. isIOS:false,
  77. }
  78. },
  79. computed: {
  80. userId() {
  81. return this.$store.state.userId;
  82. },
  83. },
  84. watch:{
  85. },
  86. beforeDestroy() {
  87. cancelAnimationFrame(requestId, this.canvas)
  88. this.worker && this.worker.terminate()
  89. setTimeout(() => {
  90. if (this.renderer instanceof THREE.WebGLRenderer) {
  91. // 遍历场景中的所有子对象,找到类型为Mesh的对象并移除
  92. let deleList = this.scene.children.filter(object=>{
  93. if (object instanceof THREE.Mesh) {
  94. return object
  95. }
  96. })
  97. if(deleList && deleList.length>0){
  98. this.scene.remove(...deleList);
  99. }
  100. this.scene.traverse(function(object) {
  101. if (object instanceof THREE.Mesh) {
  102. if(object.geometry && typeof(object.geometry.dispose)=='function'){
  103. object.geometry.dispose();
  104. }
  105. if(object.material && typeof(object.material.dispose)=='function'){
  106. object.material.dispose();
  107. }
  108. if(object.texture && typeof(object.texture.dispose)=='function'){
  109. object.texture.dispose();
  110. }
  111. }
  112. });
  113. this.renderer.clear();
  114. this.renderer.dispose();
  115. this.renderer.forceContextLoss();
  116. this.renderer.context = null;
  117. this.renderer.domElement = null;
  118. this.renderer = null;;
  119. this.clearHandle()
  120. }
  121. }, 0)
  122. this.gltfWalls = [];
  123. this.gltfSpaces = [];
  124. this.gltfSpaceRoofs = [];
  125. this.instancedMeshList = [];
  126. this.instancedSpaceMeshList = [];
  127. this.lableItem = [];
  128. this.gltfLayouts = [];
  129. this.instancedFurList = [];
  130. TWEEN && TWEEN.removeAll();//清除所有的tween;
  131. console.warn("***destroyed-webgl_rxdz_look***")
  132. },
  133. async mounted(options) {
  134. var that = this;
  135. this.houseId = this.$route.query.houseId?this.$route.query.houseId:'';
  136. this.spaceId = this.$route.query.spaceId?this.$route.query.spaceId:'';
  137. this.id = this.$route.query.id?this.$route.query.id:'';
  138. console.warn("***mounted-webgl_rxdz_look****",this.id,this.$route.query)
  139. this.isIOS = !!navigator.userAgent.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
  140. if(this.id){
  141. this.getIdData()
  142. }else{
  143. this.$store.state.loadingMsg = "没有数据~";
  144. }
  145. let screenWidth = window.screen.width;
  146. let screenHeight = window.screen.height;
  147. if(window.innerWidth && window.screen.width){
  148. screenWidth = Math.min(window.innerWidth,window.screen.width)
  149. }
  150. if(window.innerHeight && window.screen.height){
  151. screenHeight = Math.min(window.innerHeight,window.screen.height)
  152. }
  153. let container = this.$refs.webgl;
  154. let canvas3d = this.canvas = this.$refs.glcanvas;
  155. let controls = null;
  156. let camera = null, renderer = null, mixer = null;
  157. let loader = this.loader = new GLTFLoader();
  158. let scene = this.scene = new THREE.Scene();
  159. // let raycaster = null;
  160. // let mouse = new THREE.Vector2();
  161. let chooseMesh = this.chooseMesh;//标记鼠标拾取到的mesh
  162. let isUserContorl = false;//是否进入漫游状态
  163. let stats;
  164. let tweenCameraAnma = false; //表示当前是否处在动画过程中
  165. init();
  166. this.$store.state.loadingMsg="加载中...1%";
  167. this.progress = 1;
  168. this.clearEvent = clearEvent;
  169. this.tweenCameraAnmaChange = tweenCameraAnmaChange;
  170. this.updateLables = updateLables;
  171. this.moveMeshCenterHandle = moveMeshCenterHandle;
  172. this.cameraInit = cameraInit;
  173. this.resetControl = resetControl;
  174. function init() {
  175. scene.background = new THREE.Color("#FFFFFF");
  176. // 创建相机位置
  177. camera = new THREE.PerspectiveCamera( 80, screenWidth / screenHeight, 0.1, 10000 );
  178. camera.up.set(0, 1, 0);//俯视状态,将相机的up向量设置为z轴负方向
  179. scene.add(camera);
  180. that.camera = camera;
  181. // 环境光会均匀的照亮场景中的所有物体
  182. const ambientLight = new THREE.AmbientLight(0xFFEFE0, 3);
  183. scene.add(ambientLight);
  184. //平行光
  185. const light = new THREE.DirectionalLight(0xFFF8E5, 3);
  186. light.position.set(-3, 9, 3); //default; light shining from top
  187. light.castShadow = true; // default false
  188. // 默认情况下光投影相机区域是一个长宽高为10x10x500的长方体区域,光源投射方向为通过坐标原点
  189. light.shadow.camera.left = -100; // default
  190. light.shadow.camera.right = 100; // default
  191. light.shadow.camera.top = 100; // default
  192. light.shadow.camera.bottom = -100; // default
  193. light.shadow.mapSize.width = 1024; // default
  194. light.shadow.mapSize.height = 1024; // default
  195. // light.shadow.camera.near = 0.1; // default
  196. // light.shadow.camera.far = 500; // default
  197. // light.shadow.bias = -0.01;
  198. // light.shadow.radius = 1;
  199. // light.shadow.darkness = 1; // 设置阴影强度为0.5
  200. scene.add(light);
  201. //antialias 这个值得设置为false,不然IOS上截图会失效
  202. renderer = that.renderer = new THREE.WebGLRenderer({
  203. canvas:canvas3d,
  204. alpha: true,
  205. });
  206. if(!that.isIOS){
  207. renderer.shadowMap.enabled = true;//产生阴影
  208. renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 阴影属性
  209. }
  210. renderer.outputEncoding = THREE.sRGBEncoding;
  211. renderer.outputColorSpace = THREE.SRGBColorSpace;
  212. // renderer.toneMappingExposure = 0.1;//色调映射的曝光级别。默认是1
  213. renderer.toneMapping = THREE.NoToneMapping;//色调映射
  214. renderer.physicallyCorrectLights = true;//关键参数,模拟物理光照影响,必须设置为true
  215. renderer.setPixelRatio( window.devicePixelRatio );
  216. renderer.setSize( screenWidth, screenHeight );
  217. container.appendChild( renderer.domElement );
  218. // controls.target = new THREE.Vector3( that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z );;
  219. controls = new OrbitControls(camera, renderer.domElement);
  220. controls.screenSpacePanning = true;
  221. controls.enableDamping = true;
  222. controls.minDistance = 1;
  223. controls.maxDistance = 400;
  224. controls.minPolarAngle = 0;// 默认0
  225. controls.maxPolarAngle = Math.PI / 2; // 默认Math.PI,即可以向下旋转到的视角。
  226. controls.target.set(that.controlStarPosition.x, that.controlStarPosition.y, that.controlStarPosition.z);
  227. controls.enableZoom = true;//启用摄像机的缩放
  228. // stats = new Stats();
  229. // container.appendChild(stats.dom);
  230. // stats.domElement.style.top = '100px';
  231. // 监听
  232. window.addEventListener( 'resize', onWindowResize );
  233. // raycaster = new THREE.Raycaster();
  234. renderer.domElement.addEventListener('touchstart', onPointerStart, false);
  235. renderer.domElement.addEventListener('touchmove', onPointerMove, false);
  236. renderer.domElement.addEventListener('touchend', onPointerUp, false);
  237. render();//重启渲染
  238. cameraInit();
  239. controls.saveState();//保存当前控制器的状态
  240. }
  241. //初始化相机位置
  242. function cameraInit(){
  243. camera.position.set(that.cameraStarPosition.x, that.cameraStarPosition.y, that.cameraStarPosition.z);
  244. camera.lookAt(that.controlStarPosition.x,that.controlStarPosition.y,that.controlStarPosition.z);
  245. }
  246. //初始状态
  247. function resetControl(){
  248. controls.reset();
  249. }
  250. function tweenCameraAnmaChange (value) {
  251. tweenCameraAnma = value
  252. }
  253. //取消事件监听-避免二次进入时触发多次事件
  254. function clearEvent(){
  255. console.warn("**clearEvent****")
  256. renderer && renderer.domElement && renderer.domElement.removeEventListener('touchstart', onPointerStart);
  257. renderer && renderer.domElement && renderer.domElement.removeEventListener('touchmove', onPointerMove );
  258. renderer && renderer.domElement && renderer.domElement.removeEventListener('touchend', onPointerUp );
  259. }
  260. // 手指移动开始
  261. function onPointerStart(event){
  262. console.log('开始触摸事件:',that.overChange)
  263. if(that.overChange){//形变中,不能相应用户操作
  264. return false;
  265. }
  266. }
  267. //持续触摸中
  268. function onPointerMove( event ) {
  269. if(that.overChange){//形变中,不能相应用户操作
  270. return false;
  271. }
  272. that.showLables = false;
  273. }
  274. //触摸结束
  275. function onPointerUp(event) {
  276. if(that.overChange){//形变中,不能相应用户操作
  277. return false;
  278. }
  279. // enableRender();
  280. if(event.touches.length==0){
  281. that.showLables = true;
  282. updateLables();
  283. }
  284. }
  285. //把摄像机移动的选中模型的正上方,观察点也变更为模型中心点,同时选中模型
  286. function moveMeshCenterHandle(mesh = null,noChangeColor = true){
  287. if(mesh){//如果传入了模型,则取模型
  288. let spaceId = mesh.spaceId;//空间id
  289. if(chooseMesh && spaceId == chooseMesh.spaceId){
  290. console.warn("**moveMeshCenterHandle-重复选中了***")
  291. return false;
  292. }
  293. chooseMesh = mesh;
  294. }
  295. if(!chooseMesh){
  296. console.warn("**moveMeshCenterHandle-没有数据***")
  297. return false;
  298. }
  299. that.showLables = false;//隐藏
  300. controls.enable = false;//控制器不响应用户的操作
  301. // let object = chooseMesh;//当前选中的空间模型
  302. // let spaceObj = object.userData;//获取空间模型的相关数据
  303. let spaceObj = chooseMesh;//获取空间模型的相关数据
  304. let cameraNewPosition ={};
  305. let targetNewPosition ={};
  306. let oldUp = {};
  307. let newUp = {};
  308. if (isUserContorl === false) { // 非漫游状态
  309. cameraNewPosition = {
  310. x:spaceObj.centerX/100,
  311. y:camera.position.y,
  312. z:-spaceObj.centerY/100,
  313. }
  314. //新的观察点的位置-取模型的中心点坐标,加上高度,由于模型都是贴地的,所以高度设置为0
  315. targetNewPosition = {
  316. x:spaceObj.centerX/100,
  317. y:0,
  318. z:-spaceObj.centerY/100,
  319. }
  320. oldUp = camera.up;//俯视状态
  321. newUp = camera.up;
  322. // that.cameraLastPosition = cameraNewPosition;//记录下上一次摄像头位置
  323. // that.controlLastPosition = targetNewPosition;//记录下上一次观察点位置
  324. }
  325. console.warn("**moveMeshCenter***",isUserContorl,spaceObj,JSON.stringify(camera.position),JSON.stringify(controls.target)
  326. ,cameraNewPosition,targetNewPosition,JSON.stringify(camera.up))
  327. tweenCamera(camera.position,controls.target,cameraNewPosition,targetNewPosition,oldUp,newUp,600);
  328. setTimeout(()=>{
  329. that.showLables = true;
  330. updateLables();
  331. controls.enable = true;//控制器响应用户的操作
  332. },601);//动画结束后回复原始状态
  333. }
  334. // oldP 相机原来的位置
  335. // oldT target原来的位置
  336. // newP 相机新的位置
  337. // newT target新的位置
  338. function tweenCamera(oldP, oldT, newP, newT, oldUp, newUp, time=1000) {
  339. if(JSON.stringify(oldP) == JSON.stringify(newP) && JSON.stringify(oldT) == JSON.stringify(newT)){
  340. that.repeatFlag = false;//放开限制,可以再次点击
  341. return false;
  342. }
  343. tweenCameraAnma = true;
  344. var tween = new TWEEN.Tween({
  345. x1: oldP.x, // 相机x
  346. y1: oldP.y, // 相机y
  347. z1: oldP.z, // 相机z
  348. x2: oldT.x, // 控制点的中心点x
  349. y2: oldT.y, // 控制点的中心点y
  350. z2: oldT.z, // 控制点的中心点z
  351. x3: oldUp.x, // 控制点的中心点x
  352. y3: oldUp.y, // 控制点的中心点y
  353. z3: oldUp.z // 控制点的中心点z
  354. })
  355. .to({
  356. x1: newP.x,
  357. y1: newP.y,
  358. z1: newP.z,
  359. x2: newT.x,
  360. y2: newT.y,
  361. z2: newT.z,
  362. x3: newUp.x, // up向量
  363. y3: newUp.y, // 控制点的中心点y
  364. z3: newUp.z // 控制点的中心点z
  365. }, time)
  366. .easing(TWEEN.Easing.Quadratic.InOut)
  367. .onUpdate((object)=> {
  368. camera.position.x = object.x1;
  369. camera.position.y = object.y1;
  370. camera.position.z = object.z1;
  371. let newTarget = new THREE.Vector3(object.x3,object.y3,object.z3);
  372. camera.up.copy(newTarget);
  373. camera.lookAt(object.x2,object.y2,object.z2);
  374. // controls.target.x = object.x2;
  375. // controls.target.y = object.y2;
  376. // controls.target.z = object.z2;
  377. // controls.update();
  378. // console.warn("****onUpdate**",object.x1,object.y1,object.z1,object.x2,object.y2,object.z2)
  379. }).onComplete(()=>{
  380. controls.target.x = newT.x;
  381. controls.target.y = newT.y;
  382. controls.target.z = newT.z;
  383. //修正最后的视角
  384. let up = new THREE.Vector3(newUp.x,newUp.y,newUp.z);
  385. camera.up.copy(up);
  386. camera.lookAt(controls.target.x,controls.target.y,controls.target.z);
  387. tweenCameraAnma = false;
  388. that.repeatFlag = false;//放开限制,可以再次点击
  389. })
  390. // 开始动画
  391. tween.start();
  392. }
  393. function onWindowResize() {
  394. camera.aspect = screenWidth / screenHeight;
  395. camera.updateProjectionMatrix();
  396. renderer.setSize( screenWidth, screenHeight );
  397. }
  398. //计算漫游时当前选中空间的观察点和摄像机的放置点位
  399. //distance 表示要沿着视角移动的距离
  400. function updateLables(){
  401. if(!that.showLables){
  402. return false;
  403. }
  404. that.lableItem.forEach(lable =>{
  405. let item = that.gltfSpaces[lable.cubeIndex].instancedMeshIndexList[0];//获取地板模型的第一个geometry实例
  406. let _index = item.instancedMeshIndex;//第一个geometry实例 在 全局InstancedMesh实例的位置
  407. let instancedMesh = that.instancedSpaceMeshList[_index];//获取具体的网格实例
  408. let stratMatrix = new THREE.Matrix4();//定义一个四维矩阵
  409. instancedMesh.getMatrixAt(item.instancedAtIndex,stratMatrix);//获取当前几何体的四维矩阵到stratMatrix里面
  410. let position = new THREE.Vector3();//当前几何体的位置参数
  411. position.setFromMatrixPosition(stratMatrix);//从四维向量中提取位置信息
  412. // console.warn("***updateLables***",item.instancedAtIndex,JSON.stringify(position));
  413. position.project(camera);
  414. const x = (position.x * .5 + .5) * screenWidth;
  415. const y = (position.y * -.5 + .5) * screenHeight;
  416. lable.transform = `translate(-50%, -50%) translate(${x}px,${y}px)`;
  417. })
  418. }
  419. function render() {
  420. TWEEN && TWEEN.update();
  421. // stats.update();
  422. //不处在动画过程中,则可以处理移动等动作
  423. if(tweenCameraAnma==false){
  424. controls.update();
  425. }
  426. renderer.render(scene, camera);//单次渲染
  427. requestId = requestAnimationFrame(render, canvas3d);
  428. }
  429. },
  430. methods: {
  431. clearHandle(){
  432. this.clearEvent();
  433. },
  434. //楼层切换
  435. floorChange(item){
  436. if(this.floorId==item.layoutId){
  437. return false;
  438. }
  439. this.floorId = item.layoutId;
  440. this.curHouseObj = this.curData.layoutStruct.find(it=>it.layoutId==item.layoutId);//更新当前具体的户型数据
  441. // 遍历场景中的所有子对象,找到类型为Mesh的对象并移除
  442. let deleList = this.scene.children.filter(object=>{
  443. if(object.userType=="mesh" || object.userType=="layoutMesh"){
  444. return object
  445. }
  446. })
  447. // console.warn("***deleList***",deleList)
  448. if(deleList && deleList.length>0){
  449. this.showLables = false;//隐藏lable
  450. this.scene.remove(...deleList);
  451. }
  452. this.gltfWalls = [];
  453. this.gltfSpaces = [];
  454. this.instancedMeshList = [];
  455. this.instancedSpaceMeshList = [];
  456. this.lableItem = [];
  457. this.gltfLayouts = [];
  458. this.instancedFurList = [];
  459. this.wallList = [];
  460. //恢复初始视角
  461. this.cameraInit();
  462. this.resetControl();
  463. setTimeout(()=>{
  464. this.loadSpace();
  465. }, 100);
  466. // this.$emit("curHouseFloorChange", item);//通知页面,户型楼层发生了变更
  467. },
  468. async getIdData(){
  469. let userId = this.userId || '';
  470. let params = {
  471. id: this.id,
  472. brandId: $config.brandId,
  473. houseId:this.houseId,
  474. // userId,
  475. };
  476. const res = await requestConfig('getCustomizedRecord', params);
  477. if (res.success ) {
  478. let single = res.list[0];
  479. this.layoutStruct = JSON.parse(JSON.stringify(single));
  480. this.setHouseDetail(this.layoutStruct)
  481. }
  482. },
  483. /**
  484. * 设置户型详情信息
  485. * @param {Object} data 户型详情
  486. */
  487. setHouseDetail(data){
  488. if(data && data.layoutStruct){
  489. let curData = data;
  490. this.curHouseObj = curData.layoutStruct.find(it=>it.floor==curData.curFloor);;
  491. // this.spaceId = this.curHouseObj.spaceId;
  492. console.warn("***curHouseObj***",this.curHouseObj)
  493. this.floorList = [];
  494. curData.layoutStruct && curData.layoutStruct.forEach(item=>{
  495. this.floorList.push({
  496. houseFloor:item.floor,
  497. layoutId:item.layoutId,
  498. });
  499. })
  500. let select = this.floorList.find(it=>it.houseFloor==this.curHouseObj.floor);
  501. this.floorId = select ? select.layoutId : this.floorList[0].layoutId;
  502. this.curData = curData;
  503. console.warn("***floorList-init***",this.floorList,select)
  504. // 加载户型
  505. this.loadSpace();
  506. }else{
  507. this.curHouseObj = {}
  508. }
  509. },
  510. // 添加文字标签
  511. addWordLabel(){
  512. if(!this.gltfSpaces || this.gltfSpaces.length <= 0){
  513. return false;
  514. }
  515. // 方案二
  516. this.lableItem = [];
  517. this.gltfSpaces.forEach((cube,index) =>{
  518. // 给地板加上空间类型标注, 空间为链接空间的不显示
  519. if(cube.spaceName && !cube.isSizeLock){
  520. let name = spaceTypes[cube.spaceType - 1];
  521. if(cube.spaceType==15){ //更改空间显示名称 X空间 类型 根据布局所属类型来显示
  522. let layoutId = this.spaceList.find(it => it.spaceId == cube.spaceId).layoutId;
  523. let layout = this.arrFrunList.find(it=>it.id == layoutId);
  524. if(layout){
  525. name = spaceTypes[layout.type - 1];
  526. }
  527. }
  528. this.lableItem.push(
  529. {
  530. text:name,
  531. spaceId:cube.spaceId,
  532. transform:'',
  533. cubeIndex:index,
  534. }
  535. )
  536. }
  537. })
  538. this.showLables = true;
  539. this.updateLables();//更新lable
  540. },
  541. //obj 物体对象,type 是否改变颜色
  542. moveMeshCenter(obj,type){
  543. console.warn("**moveMeshCenter***",obj)
  544. if(obj && this.gltfSpaces && this.gltfSpaces.length>0){
  545. this.moveMeshCenterHandle(obj,type);
  546. }
  547. },
  548. // 绘制空间-即地板
  549. async loadSpace(){
  550. this.spaceList = [];
  551. this.wallIds = [];
  552. if(!this.curHouseObj){//减少重复请求
  553. console.warn("***数据错误***")
  554. return false
  555. }
  556. if(this.curHouseObj){
  557. const spaceDetail = this.curHouseObj;
  558. const spaceList = spaceDetail.houseJson;
  559. // 交换centerX, centerY;上一页面已经处理过了,这里不在需要处理
  560. for (let index = 0; index < spaceList.length; index++) {
  561. var element = spaceList[index];
  562. // const centerX = JSON.parse(JSON.stringify(element.centerX))
  563. // element.centerX = element.centerY;
  564. // element.centerY = centerX;
  565. // 计算观察点向量(相对中心点)
  566. let _actorLoaction = element.actorLocation.split(',');//x y z
  567. let _x = parseInt(_actorLoaction[1]) || element.centerX;//观察点 X轴坐标
  568. let _z = (parseInt(_actorLoaction[0])) || element.centerY;//观察点 Z轴坐标
  569. let _presentX = (_x - element.centerX)/((element.spaceWidth/2) - 5);//5是墙壁厚度的一半-单位cm
  570. let _presentY = (_z - element.centerY)/((element.spaceHeight/2) - 5);
  571. element.presentX = _presentX;//观察点跟空间中心原点的距离比例
  572. element.presentY = _presentY;
  573. element.wallMoveValue = "[0,0,0,0]"
  574. this.spaceList.push(element);
  575. this.wallIds.push(element.wallId);
  576. if(element.wallList){
  577. this.wallList.push(JSON.parse(element.wallList));
  578. }
  579. if(element.isSelected){ // 默认选中空间
  580. this.curSpaceObj = element;
  581. }
  582. }
  583. if(!this.curSpaceObj && this.spaceList.length > 0){
  584. this.curSpaceObj = this.spaceList[0];
  585. }
  586. }
  587. console.log("该户型空间数据:", this.spaceList);
  588. console.log("当前选中的空间:", this.curSpaceObj);
  589. this.loaderSpaceArr(this.spaceList);
  590. // 获取墙体数据并且绘制墙体
  591. this.getHouseTypeSpaceWalls();
  592. },
  593. // 获取墙体数据
  594. async getHouseTypeSpaceWalls(){
  595. // let data = {id:this.wallIds}
  596. // const res = await requestConfig('getHouseTypeSpaceWalls', data, true);
  597. // console.log("墙体数据:", res.list)
  598. // let wallList = [];
  599. // if(res.success){
  600. // wallList = this.wallList = res.list;
  601. // }
  602. let wallList = [];
  603. if(this.wallList && this.wallList.length>0){
  604. wallList = this.wallList;
  605. }else{
  606. let data = {id:this.wallIds}
  607. const res = await requestConfig('getHouseTypeSpaceWalls', data, true);
  608. console.log("墙体数据:", res.list)
  609. if(res.success){
  610. wallList = this.wallList = res.list;
  611. }
  612. }
  613. let wallArr = []
  614. for (let index = 0; index < wallList.length; index++) {//每个空间对应一个数据
  615. let element = JSON.parse(wallList[index].wallJson);
  616. let space = this.spaceList.find(space=>space.spaceId==element.spaceId);
  617. this.computeWallHandleOld(space,element);//提前计算
  618. for (let i = 0; i < element.wallData.length; i ++) {//对应空间里面的4个方向的墙壁数据
  619. let wallData = element.wallData[i];
  620. //对应方向的墙壁的墙体模型数据列表,每一面墙可能有多个模型
  621. for (let j = 0; j < wallData.wallModelData.length; j ++) {
  622. let wallModelData = wallData.wallModelData[j];
  623. wallArr.push({spaceId:element.spaceId, wallModelData:wallModelData, wallDirection:wallData.wallDirection})
  624. }
  625. }
  626. }
  627. this.loadSpaceObjWalls(wallArr, wallList);
  628. this.getOverallArrangementDetailsList(2);
  629. },
  630. // 加载单个空间墙体资源
  631. async loadSpaceObjWalls(wallArr, wallList){
  632. // 加载远程墙体模型资源
  633. let startTime = new Date().getTime();
  634. // console.log("wallArr:", wallArr)
  635. let promise_list = [];
  636. let realWallArr = this.preWallData(wallArr);
  637. let arrLength = realWallArr.length;
  638. realWallArr && realWallArr.forEach((item,index) => {
  639. promise_list.push(
  640. new Promise((resolve, reject) => {
  641. this.loadWallModels(item, wallList, arrLength , resolve);
  642. })
  643. )
  644. });
  645. Promise.all(promise_list).then(()=>{
  646. let endTime = new Date().getTime();
  647. console.log("模型全部加载完成,时间:",endTime - startTime);
  648. this.$nextTick(()=>{
  649. this.moveMeshCenter(this.curSpaceObj);
  650. this.progress = 100;
  651. // this.$refs.myLoading.showLoading("加载中..." + this.progress + '%')
  652. this.$store.state.loadingMsg="加载中..." + this.progress + '%';
  653. this.$nextTick(()=>{
  654. this.myLoadingStatus = false;
  655. // this.$refs.myLoading.hideLoading();
  656. setTimeout(()=>{
  657. this.addWordLabel(); // 添加文字标签
  658. }, 610);
  659. })
  660. })
  661. })
  662. },
  663. }
  664. }
  665. </script>
  666. <style lang="scss" scoped>
  667. @import "./webgl_rxdz_look.scss";
  668. </style>