zjs_project 4 天之前
父节点
当前提交
19e4de1de6

+ 2 - 2
src/components/newQCCom/viewMask/viewMask.html

@@ -53,7 +53,7 @@
 		</div> -->
 	<!-- </div> -->
     <!-- 右侧按钮  -->
-    <div class="btn-view columns" style="left: unset;right: 20px;" v-if="showAIImage && (aiImagesList && aiImagesList.length>0)">
+    <div class="btn-view columns right-view" v-if="showAIImage && (aiImagesList && aiImagesList.length>0)">
     	<!-- 下载 -->
     	<div class="compareBtn btn1" @click.stop="save">
     		<img class="down" src="https://dm.static.elab-plus.com/miniProgram/iconfont/down.png" mode="widthFix"/>
@@ -63,7 +63,7 @@
     		<img class="compareIcon" src="https://dm.static.elab-plus.com/miniProgram/space1/compareAI_btn.png" mode="widthFix" />
     	</div>
     </div>
-    <div class="btn-view columns" style="left: unset;right: 20px;" v-if="showAIImage==false">
+    <div class="btn-view columns right-view" v-if="showAIImage==false">
     	<!-- 切换视图-退出当前模式 -->
     	<div class="compareBtn btn1" @click.stop="showOrHideWebGl" v-if="aiImagesList && aiImagesList.length>0">
     		<img class="compareIcon" src="https://dm.static.elab-plus.com/miniProgram/space1/compareAI_btn.png" mode="widthFix" />

+ 5 - 2
src/components/newQCCom/viewMask/viewMask.scss

@@ -28,7 +28,7 @@
 }
 .btn-view{
 	position: absolute;
-	top: 120px;
+	top: 220px;
 	left: 20px;
 	width: 72px;
 	z-index: 16;
@@ -101,7 +101,10 @@
 		height: 39px;
 	}
 }
-
+.right-view{
+    left: unset;
+    right:20px!important;
+}
 .layout-view{
 	position: absolute;
 	bottom:0px;

+ 5 - 29
src/components/newQCCom/viewMask/viewMask.vue

@@ -365,7 +365,7 @@
                 this.themeIndex = aiObj.themeIndex;
                 console.warn("***syncData-space***",aiObj)
             },
-			//切换空间
+			//切换空间-会请求接口更新当前空间的风格数据
 			changeSpace(item){
 				this.$parent.changeSpace(item.spaceId);
                 //已经生成的AI图片中找到切换到的空间
@@ -714,30 +714,6 @@
 					util.trackRequest(param);
 				}
 			},
-			image2Base64(imgUrl) {//导入的图片路径
-				var toBase64= new Promise(function(resolve, reject){
-				    window.URL = window.URL || window.webkitURL;
-				    var xhr = new XMLHttpRequest();
-				    xhr.open("get", imgUrl, true);
-				    // 至关重要
-				    xhr.responseType = "blob";//文件流
-				    xhr.onload = function (res) {
-				        if (res.currentTarget.status == 200) {
-				            //得到一个blob对象
-				            var blob = res.currentTarget.response;
-				            // 至关重要
-				            let oFileReader = new FileReader();
-				            oFileReader.onloadend = function (e) {
-					            let base64 = e.target.result;//base64
-					            resolve(base64)
-				            };
-				            oFileReader.readAsDataURL(blob);
-				        }
-			        }
-				    xhr.send();
-			    });
-				return toBase64;
-			},
 			changeImg2Base64(url, isRepeat) {
 				var self = this;
 				if(isRepeat && self.inputBase64Url){//重复使用
@@ -773,10 +749,10 @@
 				if(!this.styleList || this.curStyleIndex < 0 || !this.styleList[this.curStyleIndex].imgUrl){
 					return false
 				}
-				if(this.$parent.pvCurPageName!="room_show"){//说明用户切换页面了
-					console.warn("***用户已经退出页面***")
-					return false;
-				}
+				// if(this.$parent.pvCurPageName!="room_show"){//说明用户切换页面了
+				// 	console.warn("***用户已经退出页面***")
+				// 	return false;
+				// }
 				let imgUrl = this.styleList[this.curStyleIndex].imgUrl;
 				let subType = this.subType;
 				let session_hash = Date.now();

+ 4 - 1
src/pages/webgl_rxdz_test_all/webgl_rxdz_test_all.html

@@ -26,7 +26,7 @@
 	</canvas>
 	<!-- 主要操作视图 -->
 	<viewShell ref="viewShell" pageType="1" :overChange="overChange" :houseObj="curHouseObj" :floorList="floorList"
-	@curSpaceChange="curSpaceChange" @curHouseFloorChange="curHouseFloorChange"></viewShell>
+	@curSpaceChange="curSpaceChange" @curHouseFloorChange="curHouseFloorChange" v-show="showRoam==false"></viewShell>
 	<!-- @click="goRoam(gltf)" -->
 	<div v-show="showLables && gltf.text.length>0 && gltf.transform" v-for="(gltf,index) in lableItem" :key="index" class="word-view"
 	:style="{'transform':gltf.transform}" >
@@ -35,6 +35,9 @@
 		<!-- 更改功能按钮 -->
 		<!-- <div class="change-view rows justify-center" @click="enterPlot(gltf)" v-if="selectSpace && selectSpace.spaceId==gltf.spaceId">更改功能</div> -->
 	</div>
+    <!-- AI结果覆盖层 -->
+    <viewMask ref="viewMask" @switchActor="switchActor" style="z-index: 13;" v-show="showRoam"
+      :spaceObj="curSpaceObj" :spaceList="spaceList" :layoutList="arrFrunList" ></viewMask>
     <!-- <contrastImg c-style="width: 100%;height: 500px;overflow: hidden;position: absolute;"
         mode="aspectFill"  type="2" leftSrc="https://elab-marketing-web.oss-accelerate.aliyuncs.com/aiBeauty/1748401728858.png"
         ></contrastImg> -->

+ 504 - 151
src/pages/webgl_rxdz_test_all/webgl_rxdz_test_all.vue

@@ -25,10 +25,11 @@
 	import loadModel from '@/mixins/loadModel.js';
 	import commonPageMethod from '@/mixins/commonPageMethod.js';
 	import viewShell from'@/components/newQCCom/viewShell/viewShell.vue';
+    import viewMask from'@/components/newQCCom/viewMask/viewMask.vue';
 	// import contrastImg from'@/components/contrastImg/contrastImg.vue';
 	export default {
 		name:"webgl_rxdz",
-		components:{viewShell},
+		components:{viewShell,viewMask},
 		mixins:[screenshot,floorMethod,wallMethod,loadModel,commonPageMethod],
 		/**
 		 * 页面的初始数据
@@ -114,7 +115,7 @@
 				minspace2: null,
 				minspace3: null,
 				minspace4 : null,
-
+                
 				spaces1 : [],
 				spaces2 : [],
 				spaces3 : [],
@@ -137,6 +138,12 @@
 				changeStatus:false,
                 floorList:[],
                 // selectIndex:'',
+                
+                actors:[], //视角数组
+                defaulIndex:null,	//默认视角的序号
+                currentActor:null,
+                circleGroup:null,//圆形地标
+                showRoam:false,//是否显示漫游时的底部功能弹窗-默认不显示
 			}
 		},
 		beforeDestroy() {
@@ -229,6 +236,14 @@
 			let needRender = false;	//是否需要渲染 false表示不需要渲染;true 表示需要渲染
 			let frustumSize = 30;//正交相机的视窗宽度距离
 			let stats;
+            
+            let raycaster = null;
+            let mouse = new THREE.Vector2();
+            let boundary=null;
+            let onPointerDownMouseX = 0, onPointerDownMouseY = 0;
+            let fingerCount = 0;	//触摸时的手指数目
+            let startTime = 0;	//非漫游时的移动变量
+            let roam = false;//是否进入漫游状态
 			init();
 			// render();
 			// this.$refs.myLoading.showLoading("加载中..." + this.progress+"%")
@@ -246,7 +261,9 @@
 			this.stopRender = stopRender;//对外暴露停止渲染的方法
 			this.cameraInit = cameraInit;
 			this.resetControl = resetControl;
-            this.setControlTarget = setControlTarget;
+            this.positionCamer = positionCamer;
+            this.switchActor = switchActor;
+            this.outRoam = outRoam;
 			if(this.curHouseObj){
 				this.houseInit()
 			}else{
@@ -255,7 +272,6 @@
 			function init() {
 
                 scene.background = new THREE.Color("#FFFFFF");
-                // scene.environment = new THREE.Color("#F2F2F2");
 
 				// 创建相机位置-投影相机
 				camera = new THREE.PerspectiveCamera( 80, screenWidth / that.canvasHeight, 0.1, 10000 );
@@ -287,12 +303,7 @@
 				
 				light.shadow.mapSize.width = 8192; // default
 				light.shadow.mapSize.height = 8192; // default
-				// light.shadow.camera.near = 0.1; // default
-				// light.shadow.camera.far = 500; // default
-				
-				// light.shadow.bias = -0.01;
-				// light.shadow.radius = 1;
-				// light.shadow.darkness = 1; // 设置阴影强度为0.5
+
                 scene.add(light);
 				
 				// const helper = new THREE.CameraHelper( light.shadow.camera );
@@ -333,6 +344,7 @@
 				controls.enableZoom = true;//启用摄像机的缩放
 				controls.enablePan  = false;//启用或禁用摄像机平移,默认为true
 				
+                raycaster = new THREE.Raycaster();
 				// 监听相机移动事件-限制只能在当前空间范围内移动
 				// controls.addEventListener('change', () => {
 				// 	// 检查相机位置是否超出边界框
@@ -357,11 +369,24 @@
             function resetControl(){
             	controls.reset();
             }
-            //设置控制器的焦点
-            function setControlTarget(target){
-                if(target.isVector3){
-                    controls.target = target;
+            //控制器变化的事件监听处理
+            function controlEventHandle(){
+                // 检查相机位置是否超出边界框
+                if (boundary && !boundary.containsPoint(camera.position)) {
+                	let clampedPosition = new THREE.Vector3( );
+                	boundary.clampPoint(camera.position,clampedPosition);
+                	if(clampedPosition){
+                		camera.position.copy(clampedPosition);
+                	}
                 }
+            }
+            //设置控制器的焦点
+            function controlAddEvent(target){
+                controls.addEventListener('change', controlEventHandle);
+            }
+            //移除控制器的焦点
+            function controlDelEvent(target){
+                controls.removeEventListener('change', controlEventHandle);
             }
 			function onWindowResize() {
 			    camera.aspect = screenWidth / that.canvasHeight;
@@ -371,9 +396,9 @@
 			}
 			function attendEvent () {
 				window.addEventListener('resize', onWindowResize);
-				// renderer.domElement.addEventListener('touchstart', onPointerStart, false);
-				// renderer.domElement.addEventListener('touchmove', onPointerMove, false);
-				// renderer.domElement.addEventListener('touchend', onPointerUp, false);
+				renderer.domElement.addEventListener('touchstart', onPointerStart, false);
+				renderer.domElement.addEventListener('touchmove', onPointerMove, false);
+				renderer.domElement.addEventListener('touchend', onPointerUp, false);
 			}
 			function tweenCameraAnmaChange (value) {
 				tweenCameraAnma = value
@@ -384,22 +409,36 @@
 			//取消事件监听-避免二次进入时触发多次事件
 			function clearEvent(){
 				console.warn("**clearEvent****")
-				// renderer && renderer.domElement && renderer.domElement.removeEventListener('touchstart', onPointerStart);
-				// renderer && renderer.domElement && renderer.domElement.removeEventListener('touchmove', onPointerMove );
-				// renderer && renderer.domElement && renderer.domElement.removeEventListener('touchend', onPointerUp );
+				renderer && renderer.domElement && renderer.domElement.removeEventListener('touchstart', onPointerStart);
+				renderer && renderer.domElement && renderer.domElement.removeEventListener('touchmove', onPointerMove );
+				renderer && renderer.domElement && renderer.domElement.removeEventListener('touchend', onPointerUp );
 			}
 			// 手指移动开始
 			function onPointerStart(event){
-				console.log('开始触摸事件:',that.overChange)
 				if(that.overChange){//形变中,不能相应用户操作
 					return false;
 				}
+                if(!roam){//非漫游状态不予监听
+                    return false;
+                }
+                startTime = (new Date()).getTime();
+                fingerCount = event.touches.length;//手指个数
+                console.log('开始触摸事件:',fingerCount,camera.position.y)
+                if (fingerCount === 1) {
+                    // 只有一个手指时记录当前点的坐标作为平移起始点
+                    onPointerDownMouseX = event.changedTouches[0].clientX;
+                    onPointerDownMouseY = event.changedTouches[0].clientY;
+                }
 			}
 			//持续触摸中
 			function onPointerMove( event ) {
 				if(that.overChange){//形变中,不能相应用户操作
 					return false;
 				}
+                if(!roam){//非漫游状态不予监听
+                    return false;
+                }
+                fingerCount = event.touches.length;//手指个数
 				// that.showLables = false;
 			}
 			//触摸结束
@@ -407,12 +446,366 @@
 				if(that.overChange){//形变中,不能相应用户操作
 					return false;
 				}
+                if(!roam){//非漫游状态不予监听
+                    return false;
+                }
 				// enableRender();
-				if(event.touches.length==0){
-					// that.showLables = true;
-					// updateLables();
-				}
+                fingerCount = event.touches.length;//手指个数
+                console.warn("***触摸结束***",fingerCount,startTime)
+                if(fingerCount==0 && startTime){
+                	let now = new Date().getTime()
+                	if (Math.abs(event.changedTouches[0].clientX - onPointerDownMouseX) < 10 
+                	&& Math.abs(event.changedTouches[0].clientY - onPointerDownMouseY) < 10 
+                	&& (now - startTime) < 300 ){
+                		checkIntersection(event);
+                	}
+                }
 			}
+            // start-页面2里面的相关方法
+            //进入漫游状态
+            function inRoam(){
+                roam = true;//进入漫游状态
+                that.showLables = false;//隐藏
+                that.showRoam = true;//显示漫游时的底部
+                controlAddEvent();//给控制器添加监听器,不让摄像头超过当前空间
+                controls.minDistance = 0.0001;
+                controls.maxDistance = 10;
+                controls.minPolarAngle = 0;// 默认0
+            }
+            function outRoam(){
+                roam = false;//退出漫游状态
+                that.showLables = true;//显示labbl
+                that.showRoam = false;//显示漫游时的底部
+                controlDelEvent();
+                controls.minDistance = 1;
+                controls.maxDistance = 400;
+                controls.minPolarAngle = Math.PI / 8;// 默认0
+            }
+            //计算当前选中空间的平视时的观察点和摄像机的放置点位
+            function roamPositionHandle(lon=''){
+            	if(!chooseMesh){
+            		console.error("[roamPositionHandle],没有选中的空间数据")
+            		return false;
+            	}
+            	let spaceObj = chooseMesh;//获取选中的空间模型的相关数据
+            	//获取视角
+            	let defaultActor = null;
+            	if(spaceObj.actors && spaceObj.actors.length>0){
+            		defaultActor = spaceObj.actors.find(it=>it.isSelected==true);
+            		if(!defaultActor){
+            			defaultActor = spaceObj.actors[0];
+            		}
+            	}
+            	let _actorLoaction = defaultActor.actorLocation.split(',');//x y z
+            	let _actorTransform = defaultActor.actorTransform.split(',');//旋转角度,取第三个值
+            	let _hd = THREE.MathUtils.degToRad(parseInt(_actorTransform[2]) + lon);//将度转化为弧度。
+            	let _hdY = THREE.MathUtils.degToRad(parseInt(_actorTransform[1]));//Y轴方向上将度转化为弧度。
+            	// if(parseInt(_actorLoaction[1])==0){//X轴
+            	// 	_actorLoaction[1] = spaceObj.centerX;
+            	// }
+            	// if(parseInt(_actorLoaction[0])==0){//Y轴
+            	// 	_actorLoaction[0] = spaceObj.centerY;
+            	// }
+            	let X_C = parseInt(_actorLoaction[0]);//X轴偏移量-UE原因
+            	let Y_C = -parseInt(_actorLoaction[1]);//Y轴偏移量-取反,UE里面的Y轴方向跟Three.js相反
+            	let px = spaceObj.centerX + X_C;
+            	let py = -spaceObj.centerY + Y_C;
+            	//新的摄像机的位置-新的摄像机角度是倾斜角度,所以z值需要计算,高度设置为模型高度的2倍
+            	let cameraNewPosition = {
+            		x:(parseInt(px))/100,
+            		y:1.5, 
+            		z:(parseInt(py))/100,//模型Y轴坐标系正负值跟webglZ轴是相反的
+            	}
+            	if(cameraNewPosition){
+            		let minX = 0,maxX = 0,minY = 0,maxY = 0;//0.1 是模型墙壁厚度
+            		minX = (spaceObj.centerX - (spaceObj.spaceWidth/2))/100 + 0.1;
+            		maxX = (spaceObj.centerX + (spaceObj.spaceWidth/2))/100 - 0.1;
+            		maxY = ((-spaceObj.centerY + (spaceObj.spaceHeight/2))/100 - 0.1);
+            		minY = ((-spaceObj.centerY - (spaceObj.spaceHeight/2))/100 + 0.1);
+            		//新的坐标轴不在房间范围内,则不能移动
+            		if(cameraNewPosition.x<minX || cameraNewPosition.x>maxX
+            		||cameraNewPosition.z<minY || cameraNewPosition.z>maxY){//不在房间范围
+            			let _x = ((spaceObj.spaceWidth/2) - 15)*defaultActor.presentX + spaceObj.centerX;
+            			let _z = ((spaceObj.spaceHeight/2) - 15)*defaultActor.presentY + (-spaceObj.centerY);
+            			cameraNewPosition.x = _x/100;
+            			cameraNewPosition.z = _z/100;
+            			console.warn("**roamPositionHandle-观察点不在空间范围-强制修正观察点位置****",JSON.stringify(cameraNewPosition))
+            		}
+            	}
+            	//新的观察点的位置-取模型的中心点坐标,加上高度,由于模型都是贴地的,所以高度设置为1.5
+            	let targetNewPosition = {
+            		x:cameraNewPosition.x + Math.sin(_hd),
+            		y:1.5 + Math.tan(_hdY),
+            		z:(cameraNewPosition.z - Math.cos(_hd)),
+            	}
+            	let lookPosition = {
+            		x:cameraNewPosition.x + (Math.sin(_hd)*0.01),
+            		y:1.5 + Math.tan(_hdY),
+            		z:(cameraNewPosition.z - (Math.cos(_hd))*0.01),
+            	}
+            	return {cameraNewPosition,targetNewPosition,lookPosition}
+            }
+            //直接定位到摄像头位置
+            function positionCamer(mesh=null,needAni=false){
+            	if(mesh){//如果传入了模型,则取模型
+            		chooseMesh = mesh;
+            	}
+                console.warn("[positionCamer],",chooseMesh)
+            	if(!chooseMesh){
+            		console.error("[positionCamer],没有选中的空间数据")
+            		return false;
+            	}
+            	if(!chooseMesh.actors || chooseMesh.actors.length==0){
+            		chooseMesh.actors = [{
+            			actorLocation:chooseMesh.actorLocation,
+            			actorTransform:chooseMesh.actorTransform,
+            			isSelected:true,
+            			presentX:chooseMesh.presentX,
+            			presentY:chooseMesh.presentY,
+            		}]
+            	}
+            	boundary = new THREE.Box3(
+            		new THREE.Vector3(chooseMesh.centerX/100 - chooseMesh.spaceWidth/100/2 + 0.1, 0, -chooseMesh.centerY/100 - chooseMesh.spaceHeight/100/2 + 0.1), // 边界框的最小点
+            		new THREE.Vector3(chooseMesh.centerX/100 + chooseMesh.spaceWidth/100/2 - 0.1, 2.7, -chooseMesh.centerY/100 + chooseMesh.spaceHeight/100/2 - 0.1) // 边界框的最大点
+            	);
+                inRoam();
+            	initActor();//初始化视角
+            	let data = roamPositionHandle();
+            	let cameraNewPosition = data.cameraNewPosition;
+            	let targetNewPosition = data.targetNewPosition;
+            	targetNewPosition.z = targetNewPosition.z;//增加偏差,防止极点翻转问题?不知道为啥会有用
+            	let lookPosition = data.lookPosition;
+            	creatMoveTip(cameraNewPosition);//创建移动的地标
+            	if(needAni){
+            		let oldUp = {x:0,y:1,z:0};	//俯视
+            		let newUp = {x:0,y:1,z:0};	//正视
+            		tweenCamera(camera.position,controls.target,cameraNewPosition,targetNewPosition,oldUp,newUp,2000);
+            	}else{
+            		camera.position.set(cameraNewPosition.x, cameraNewPosition.y, cameraNewPosition.z);
+            		controls.target.set(lookPosition.x,lookPosition.y,lookPosition.z);
+            		// controls.target.set(cameraNewPosition.x,cameraNewPosition.y,cameraNewPosition.z);
+            		// controls.target.copy(camera.position);
+            		camera.lookAt(targetNewPosition.x,targetNewPosition.y,targetNewPosition.z);
+            	}
+            }
+            //自动切换视角
+            function switchActor (toIndex=null) {
+            	if(!that.currentActor){
+            		this.$message.warning("没有当前视角!");
+            		return false;
+            	}
+            	if(!that.actors || that.actors.length==0){
+            		this.$message.warning("没有视角!");
+            		return false;
+            	}
+            	if(toIndex!=null){//存在要去往的视角
+            		moveActor(that.actors[toIndex]);
+            	}else{
+            		let index = that.currentActor.userIndex;//当前视角的序号
+            		let nextIndex = (index + 1) % that.actors.length;
+            		//移动到对应的视角去
+            		moveActor(that.actors[nextIndex]);
+            		that.defaulIndex = nextIndex;//更新下默认视角
+            	}
+            }
+            //移动到选中的位置-地板
+            function moveCarmer (point) {
+            	//还在动画中,不能点击切换
+            	if(tweenCameraAnma == true){
+            		return false;
+            	}
+            	let _x =  point.x - camera.position.x;//x轴移动的距离
+            	let _z =  point.z - camera.position.z;//z轴移动的距离
+            	let cameraNewPosition = {x:camera.position.x + _x,y:1.5,z:camera.position.z + _z};
+            	let targetNewPosition = {x:controls.target.x + _x,y:1.5,z:controls.target.z + _z};
+            	let oldUp = {x:0,y:1,z:0};	
+            	let newUp = {x:0,y:1,z:0};
+            	moveTip(cameraNewPosition)
+            	// console.warn("**moveCarmer***",lon,JSON.stringify(cameraNewPosition),JSON.stringify(targetNewPosition))
+            	tweenCamera(camera.position,controls.target,cameraNewPosition,targetNewPosition,oldUp,newUp,2000);
+            	setTimeout(()=> {
+            		that.circleGroup.visible = false;
+            	}, 2000);
+            }
+            //创建地标
+            function creatMoveTip(position){
+            	if(!that.circleGroup){
+            		that.circleGroup = new THREE.Group();
+            		let geometry = new THREE.CircleGeometry( 0.2, 32 );
+            		let material = new THREE.MeshBasicMaterial( { transparent: true } );
+            		let circle = new THREE.Mesh( geometry, material );
+            		circle.position.set(position.x,0.01,position.z);
+            		circle.rotation.x = -Math.PI / 2;
+            		// let geometry1 = new THREE.CircleGeometry( 0.4, 32 );
+            		// let circle2 = new THREE.Mesh( geometry1, material );
+            		// circle2.position.set(position.x,0.01,position.z);
+            		// 使用贴图
+            		const textureLoader = new THREE.TextureLoader();
+            		textureLoader.load('https://dm.static.elab-plus.com/miniProgram/circlemap1.png', function(texture) {
+            			material.map = texture; // 将贴图应用于材质的map属性
+            			material.needsUpdate = true; // 更新材质
+            		});
+            		that.circleGroup.add(circle);
+            		scene.add(that.circleGroup);
+            		that.circleGroup.visible = false;
+            	}
+            }
+            //移动地标
+            function moveTip(position){
+            	if(!that.circleGroup){
+            		that.circleGroup = new THREE.Group();
+            		let geometry = new THREE.CircleGeometry( 0.2, 32 );
+            		let material = new THREE.MeshBasicMaterial( { color: 0xffffff } );
+            		let circle = new THREE.Mesh( geometry, material );
+            		circle.position.set(position.x,0.01,position.z);
+            		circle.rotation.x = -Math.PI / 2;
+            		// let geometry1 = new THREE.CircleGeometry( 0.4, 32 );
+            		// let circle2 = new THREE.Mesh( geometry1, material );
+            		// circle2.position.set(position.x,0.01,position.z);
+            		that.circleGroup.add(circle);
+            		scene.add(that.circleGroup);
+            	}else{
+            		that.circleGroup.visible = true;
+            		that.circleGroup.children[0].position.set(position.x,0.01,position.z);
+            	}
+            }
+            //移动视角点位
+            function moveActor (obj) {
+            	clearEvent();//注销事件监听
+            	// console.warn("***moveActor***",obj)
+            	that.currentActor = obj;//记录下当前的视角对象 mesh网格模型
+            	let cameraNewPosition = obj.position;
+            	let targetNewPosition = obj.targetNewPosition;
+            	let oldUp = {x:0,y:1,z:0};	//俯视
+            	let newUp = {x:0,y:1,z:0};	//正视
+            	// moveTip(cameraNewPosition);
+            	// console.warn("**moveActor***",JSON.stringify(cameraNewPosition),JSON.stringify(targetNewPosition))
+            	tweenCamera(camera.position,controls.target,cameraNewPosition,targetNewPosition,oldUp,newUp,2000);
+            	lon = 0;
+            	setTimeout(()=> {
+            		attendEvent()
+            		// that.circleGroup.visible = false;
+            	}, 2000);
+            }
+            //初始化点位视角
+            function initActor(){
+            	if(!chooseMesh){
+            		console.error("[drawActor],没有选中的空间数据")
+            		return false;
+            	}
+            	let spaceObj = chooseMesh;//获取选中的空间模型的相关数据
+            	if(!spaceObj.actors){
+            		return false;
+            	}
+            	let defaulIndex = spaceObj.actors.findIndex(it=>it.isSelected==true);
+            	if(defaulIndex == -1){
+            		defaulIndex = 0;
+            	}
+            	that.defaulIndex = defaulIndex;//记录下默认视角
+            	that.actors = [];
+            	spaceObj.actors.forEach((actor,index)=>{
+
+            		let cube = {};
+            		cube.name = "actor";
+            		cube.userType = "mesh";
+            		//新的摄像机的位置-新的摄像机角度是倾斜角度,所以z值需要计算,高度设置为模型高度的2倍
+            		let _actorLoaction = actor.actorLocation.split(',');//x y z
+            		let _actorTransform = actor.actorTransform.split(',');//旋转角度,取第三个值
+            		let _hd = THREE.MathUtils.degToRad(parseInt(_actorTransform[2]));//将度转化为弧度。
+            		let _hdY = THREE.MathUtils.degToRad(parseInt(_actorTransform[1]));//Y轴方向上将度转化为弧度。
+
+            		let X_C = parseInt(_actorLoaction[0]);//X轴偏移量
+            		let Y_C = -parseInt(_actorLoaction[1]);//Y轴偏移量-取反,UE里面的Y轴方向跟Three.js相反
+            		let px = spaceObj.centerX + X_C;
+            		let py = -spaceObj.centerY + Y_C;//UE里面的centerY值跟Three.js Y轴相反;获得真实的坐标值
+            		let position = {
+            			x:(parseInt(px))/100,
+            			y:1.5, 
+            			z:(parseInt(py))/100,//模型Y轴坐标系正负值跟webglZ轴是相反的
+            		}
+            		//新的观察点的位置-取模型的中心点坐标,加上高度,由于模型都是贴地的,所以高度设置为1.5
+            		let targetNewPosition = {
+            			x:position.x + Math.sin(_hd),
+            			y:1.5 + Math.tan(_hdY),
+            			z:(position.z - Math.cos(_hd)),
+            		}
+            		cube.position = position;
+            		cube.userIndex = index;
+            		cube.actorEum = index;
+            		cube.targetNewPosition = targetNewPosition;
+            		// console.warn("*actors*",cube,defaulIndex)
+            		that.actors.push(cube);//添加视角
+            		if(index == defaulIndex){//隐藏当前视角
+            			that.currentActor = cube;//记录下当前的视角对象 mesh网格模型
+            			let param = {
+            				type: 'CLK', //埋点类型
+            				clkId: 'clk_2cmina_23080411', //点击ID
+            				clkName: 'visualangle_clk', //点击前往的页面名称
+            				clkParams: {
+            					locusName: "预制视角",
+            					type:that.actors[index].actorEum,
+                                locusValue:that.curSpaceObj.text || that.curSpaceObj.spaceName,
+            				}
+            			};
+            			util.trackRequest(param);
+            		}
+            	})
+            }
+            //射线检测handle
+            function checkIntersection(event) {
+                let x = (event.changedTouches[0].clientX / screenWidth) * 2 - 1;
+                let y = -(event.changedTouches[0].clientY / that.canvasHeight) * 2 + 1;
+                mouse.x = x;
+                mouse.y = y;
+                //更新射线
+                raycaster.setFromCamera(mouse, camera);
+                let intersects = raycaster.intersectObjects(scene.children,true);
+            	console.warn("***checkIntersection***",intersects.length)
+                if (intersects.length > 0) {
+            		//找到最近的那个网格模型物体
+            		let mesh = intersects.find((it) => {
+            			if(it.object && it.object.isMesh == true  
+            				&& it.object.parent && it.object.parent.name == 'actor'
+            				&& it.object.parent.visible == true){
+            				return true;
+            			}
+            		});
+            		
+            		//拾取到了视角,就不继续拾取了
+            		if(mesh){
+            			moveActor(mesh.object.parent);
+            			return false;
+            		}
+            		mesh = intersects.find((it) => {
+            			if(it.object && it.object.isInstancedMesh
+            				&& (it.object.name == '地板' || it.object.name == '花园') && it.object.visible == true){
+            				return true;
+            			}
+            		});
+            		//拾取到了地板
+            		if(mesh){
+            			let floor = mesh.object;
+            			let index = mesh.instanceId;//射线相交是的实例序号
+            			let spaceId = that.gltfSpaces[index].spaceId;//获取选中实例的空间id
+            			if(floor.name == "花园"){//花园
+            				return false;
+            				let selectMesh = that.gltfSpaces.find(it=>{return it.spaceType==14 && it.instancedMeshIndexList[0].instancedAtIndex==index})
+            				spaceId = selectMesh.spaceId;
+            			}else{//室内
+            				// floor.name = "地板";
+            				let selectMesh = that.gltfSpaces.find(it=>{return it.spaceType!=14 && it.instancedMeshIndexList[0].instancedAtIndex==index})
+            				spaceId = selectMesh.spaceId;
+            			}
+            			// let spaceId = that.gltfSpaces[index].spaceId;//获取选中实例的空间id
+            			console.warn("***checkIntersection-地板***",floor,index,spaceId,that.currentChangeSpaceId)
+            			//当前拾取到的是本空间的底部-意味着用户点击了地板
+            			if(floor && spaceId == that.currentChangeSpaceId){
+            				moveCarmer(mesh.point);
+            				return false;
+            			}
+            		}
+                }
+            }
 			//把摄像机移动的选中模型的正上方,观察点也变更为模型中心点,同时选中模型
 			function moveMeshCenterHandle(mesh = null,noChangeColor = true){
 				if(mesh){//如果传入了模型,则取模型
@@ -450,19 +843,12 @@
 					}
 					oldUp = camera.up;//俯视状态
 					newUp = camera.up;
-					// newUp = new THREE.Vector3(0,0,-1);
-					// that.cameraLastPosition = cameraNewPosition;//记录下上一次摄像头位置
-					// that.controlLastPosition = targetNewPosition;//记录下上一次观察点位置
-					// if(cameraNewPosition.x<0){
-					// 	cameraNewPosition.x = 0;
-					// }
 				}
 				console.warn("**moveMeshCenter***",isUserContorl,spaceObj,JSON.stringify(camera.position),JSON.stringify(controls.target)
 				,cameraNewPosition,targetNewPosition,JSON.stringify(camera.up))
 				tweenCamera(camera.position,controls.target,cameraNewPosition,targetNewPosition,oldUp,newUp,1000);
 				setTimeout(()=>{
 					that.showLables = true;
-					// camera.up = new THREE.Vector3(0,1,0);
 					// updateLables();
 				},1001);//动画结束后回复原始状态
 			}
@@ -491,47 +877,6 @@
 				// ,cameraNewPosition,targetNewPosition,JSON.stringify(camera.up))
 				tweenCamera(camera.position,controls.target,cameraNewPosition,targetNewPosition,oldUp,newUp,500);
 			}
-            //直接定位到摄像头位置
-            function positionCamer(mesh=null,needAni=false){
-            	if(mesh){//如果传入了模型,则取模型
-            		chooseMesh = mesh;
-            	}
-            	if(!chooseMesh){
-            		console.error("[positionCamer],没有选中的空间数据")
-            		return false;
-            	}
-            	if(!chooseMesh.actors || chooseMesh.actors.length==0){
-            		chooseMesh.actors = [{
-            			actorLocation:chooseMesh.actorLocation,
-            			actorTransform:chooseMesh.actorTransform,
-            			isSelected:true,
-            			presentX:chooseMesh.presentX,
-            			presentY:chooseMesh.presentY,
-            		}]
-            	}
-            	boundary = new THREE.Box3(
-            		new THREE.Vector3(chooseMesh.centerX/100 - chooseMesh.spaceWidth/100/2 + 0.1, 0, -chooseMesh.centerY/100 - chooseMesh.spaceHeight/100/2 + 0.1), // 边界框的最小点
-            		new THREE.Vector3(chooseMesh.centerX/100 + chooseMesh.spaceWidth/100/2 - 0.1, 2.7, -chooseMesh.centerY/100 + chooseMesh.spaceHeight/100/2 - 0.1) // 边界框的最大点
-            	);
-            	initActor();//初始化视角
-            	let data = roamPositionHandle();
-            	let cameraNewPosition = data.cameraNewPosition;
-            	let targetNewPosition = data.targetNewPosition;
-            	targetNewPosition.z = targetNewPosition.z;//增加偏差,防止极点翻转问题?不知道为啥会有用
-            	let lookPosition = data.lookPosition;
-            	creatMoveTip(cameraNewPosition);//创建移动的地标
-            	if(needAni){
-            		let oldUp = {x:0,y:1,z:0};	//俯视
-            		let newUp = {x:0,y:1,z:0};	//正视
-            		tweenCamera(camera.position,controls.target,cameraNewPosition,targetNewPosition,oldUp,newUp,2000);
-            	}else{
-            		camera.position.set(cameraNewPosition.x, cameraNewPosition.y, cameraNewPosition.z);
-            		controls.target.set(lookPosition.x,lookPosition.y,lookPosition.z);
-            		// controls.target.set(cameraNewPosition.x,cameraNewPosition.y,cameraNewPosition.z);
-            		// controls.target.copy(camera.position);
-            		camera.lookAt(targetNewPosition.x,targetNewPosition.y,targetNewPosition.z);
-            	}
-            }
             // oldP  相机原来的位置
             // oldT  target原来的位置
             // newP  相机新的位置
@@ -594,64 +939,7 @@
 			}
 			//高度持续变化处理 time 动画持续时间 单位秒
 			function gradientResize (time,startHeight,endHeight) {
-				// let _timeStep = 20;//单位 毫秒
-				// let unit = screenWidth / 750;//单位rpm 对应 px 的值
-				// that.canvasHeight = screenHeight - (200 * unit) + (20 * unit);
 				return false;//不在执行变化
-				let unit = screenWidth / 750;//单位rpx 对应 px 的值
-				let _height = startHeight - endHeight;//高度变化-单位rpx
-				let _jisua = that.canvasHeight;
-				let lastHeight = _jisua + (_height * unit);//动画结束时的高度值; 单位 px
-				that.canvasHeight = lastHeight;//触发css动画
-				// let step = (_height * unit) / (time*1000 / _timeStep);//真实大小 单位px
-				console.warn("***gradientResize***",lastHeight,_jisua,startHeight,endHeight)
-
-				// that.showLables = false;
-				// let canvas_webgl = document.getElementById('canvas_webgl');
-				console.log("相机变化1:", camera.position.y);
-				var tween = new TWEEN.Tween({
-				    h1: _jisua,
-				})
-				.to({
-				    h1: lastHeight,
-				}, 1000)
-				.easing(TWEEN.Easing.Linear.None)
-				.onUpdate((object)=> {
-					if(camera.isOrthographicCamera){//正交相机
-						let aspect = screenWidth / object.h1;
-						camera.left = frustumSize * aspect / - 2;
-						camera.right  = frustumSize * aspect / 2;
-						camera.top  = frustumSize / 2;
-						camera.bottom  = frustumSize / -2;
-						camera.updateProjectionMatrix();
-					}
-					else if(camera.isPerspectiveCamera){//透视相机
-						camera.aspect = screenWidth / object.h1;
-						camera.updateProjectionMatrix();
-						renderer.setSize( screenWidth, object.h1 );
-						// let step = 0.12;//每次缩放放大的尺度
-						// let _juli = step * Math.tan(Math.PI / 8);//由于观测点和相机存在角度,所以要计算每次变化尺度产生的Z轴变化量
-						// if(_height>0){
-						// 	camera.position.y = camera.position.y + step;
-						// 	camera.position.z = camera.position.z + _juli;
-						// }else{
-						// 	camera.position.y = camera.position.y - step;
-						// 	camera.position.z = camera.position.z - _juli;
-						// }
-						// that.canvasHeight = object.h1;
-					}
-				}).onComplete(()=>{
-					camera.aspect = screenWidth / that.canvasHeight;
-					camera.updateProjectionMatrix();
-					renderer.setSize(screenWidth, that.canvasHeight );
-					tweenCameraAnma = false;
-					console.log("相机变化2:", camera.position.y);
-					// that.showLables = true;
-					// updateLables();//更新lable
-				});
-				// 开始动画
-				tween.start();
-				tweenCameraAnma = true;
 			}
 			//更新lables
 			function updateLables(){
@@ -750,6 +1038,9 @@
 		},
 
 		methods: {
+            positionCamer(){},
+            switchActor(){},
+            outRoam(){},
             async getInitData(){
             	let parmas = {
             		childLayout:this.childLayout || 0,
@@ -886,6 +1177,19 @@
             		this.cameraStarPosition.y = 30;
             	}
             	this.cameraInit();
+                this.locusValue = this.curHouseObj.name + "-" + this.curHouseObj.houseArea + "㎡";
+                let param = {
+                	type: 'PV',
+                	pvId: this.pvId,
+                	locusBehaviorName: this.locusBehaviorName,
+                	pvCurPageName: this.pvCurPageName,
+                    pvCurPageParams:{
+                        link:window.location.href,
+                    },
+                	locusValue: this.locusValue,
+                    behaviorName:"空间定制",
+                };
+                util.trackRequest(param);//发送统一PV埋点
             },
             //户型楼层发生了变更
             curHouseFloorChange(item){
@@ -1085,22 +1389,22 @@
 			
 			    }
 			},
-			curSpaceSelect(data){
+			//底部空间弹窗面板选中了空间处理函数
+            curSpaceSelect(data){
 				console.warn("***curSpaceSelect***",data);
 				if(this.selectSpace){
 					this.changeSpaceColor(this.selectSpace.spaceId,2);//取消上一个空间的颜色
 				}
 				let spaceId = data.spaceId;
 				let space = this.spaceList.find(it=>it.spaceId==spaceId);
+                this.curSpaceObj = space;
 				this.selectSpace = space;
 				this.currentChangeSpaceId = spaceId;
 				this.$store.state.curSpaceId = data.spaceId;
 				
 				this.changeSpaceColor(data.spaceId,1);//设置选中空间的颜色
 				this.moveMeshCenter(space);
-                // setTimeout(()=>{
-                //     this.setControlTarget(this.allSpaceCenter)
-                // },1100)
+
 			},
 			//具体空间面积变化-拖动产生的
 			//data = {
@@ -1119,7 +1423,39 @@
 				let space = this.spaceList.find(it=>it.spaceId==this.currentChangeSpaceId);
 				this.moveMeshCenter(space);
 			},
-			
+            //漫游模式下-底部面板选中空间
+			changeSpace(spaceId){
+				console.warn("***changeSpace***",spaceId,this.currentChangeSpaceId)
+				if(spaceId == this.currentChangeSpaceId){
+					return false;
+				}
+				this.currentChangeSpaceId = spaceId;
+				this.curSpaceObj = this.spaceList.find(it=>it.spaceId == spaceId);
+				if(this.isIOS){
+					// this.furnSingleSpaceHandle(this.curSpaceObj);
+				}
+				this.positionCamer(this.curSpaceObj,true);
+				let curSpaceArea = parseFloat((this.curSpaceObj.spaceWidth * this.curSpaceObj.spaceHeight) / 10000).toFixed(1);
+				this.navbar.title = this.curSpaceObj.spaceName + "  " + curSpaceArea + "㎡";
+				document.title = this.navbar.title;
+			},
+            //页面上根据序号选中地块
+            selectSpaceHandle(gltf){
+            	if(gltf.spaceType==13){//楼梯不处理
+            		return false
+            	}
+                console.warn("***selectSpaceHandle0***",this.selectSpace)
+            	if(this.selectSpace){
+            		this.changeSpaceColor(this.selectSpace.spaceId,2);//取消上一个空间的颜色
+            	}
+            	this.selectSpace = this.spaceList.find(it=>it.spaceId==gltf.spaceId);
+                this.curSpaceObj = this.selectSpace;
+            	this.$store.state.curSpaceId = this.selectSpace.spaceId;
+            	this.currentChangeSpaceId = this.selectSpace.spaceId;
+            	// this.moveMeshCenter(this.selectSpace);
+            	this.changeSpaceColor(this.selectSpace.spaceId,1);//设置选中空间的颜色
+            	console.warn("***selectSpaceHandle***",this.selectSpace)
+            },
 			// 空间移动,
 			changCurSpaceArea(data){
 				console.log("当前户型的核心点", this.curHouseObj.houseCore, this.overChange);
@@ -1868,21 +2204,7 @@
 				// this.selectSpace = this.spaceList.find(it=>it.spaceId==gltf.spaceId);
 				this.$refs.viewShell.changeStyleType(3,this.selectSpace)
 			},
-			selectSpaceHandle(gltf){
-				if(gltf.spaceType==13){//楼梯不处理
-					return false
-				}
-                console.warn("***selectSpaceHandle0***",this.selectSpace)
-				if(this.selectSpace){
-					this.changeSpaceColor(this.selectSpace.spaceId,2);//取消上一个空间的颜色
-				}
-				this.selectSpace = this.spaceList.find(it=>it.spaceId==gltf.spaceId);
-				this.$store.state.curSpaceId = this.selectSpace.spaceId;
-				this.currentChangeSpaceId = this.selectSpace.spaceId;
-				// this.moveMeshCenter(this.selectSpace);
-				this.changeSpaceColor(this.selectSpace.spaceId,1);//设置选中空间的颜色
-				console.warn("***selectSpaceHandle***",this.selectSpace)
-			},
+			
 			//用户选择的布局id-需要切换到这个布局去
 			userSelectPlot(layoutObj,space=null){
 				if(!layoutObj){
@@ -1939,6 +2261,8 @@
 					return false;
 				}
 				this.repeatFlag = true;
+                let space = this.spaceList.find(it=>it.spaceId==spaceId);
+                this.positionCamer(space,true);//动画的方式进入
 				// router.push({
 				// 	name: "webgl_rxdz_test_roam",
 				// 	query:data
@@ -1961,7 +2285,14 @@
 				}
 			},
             locationHandle(){
-                this.movePositionHandle(this.allSpaceCenter,this.cameraStarPosition.y);//把摄像机移动到所有模型的中心点(水平面中心)
+                //当前在漫游模式下
+                if(this.showRoam){
+                    this.outRoam();
+                    this.cameraInit();//把摄像头等属性还原到初始设置的
+                    this.movePositionHandle(this.allSpaceCenter);//把摄像机移动到所有模型的中心点(水平面中心)
+                }else{
+                    this.movePositionHandle(this.allSpaceCenter,this.cameraStarPosition.y);//把摄像机移动到所有模型的中心点(水平面中心)
+                }
             },
             // 绘制地板
             async loadSpace(){
@@ -1984,6 +2315,28 @@
                         // const centerX = JSON.parse(JSON.stringify(element.centerX))
                         // element.centerX = element.centerY;
                         // element.centerY = centerX;
+                        if(!element.actors || element.actors.length==0){
+                        	element.actors = [{
+                        		actorLocation:element.actorLocation,
+                        		actorTransform:element.actorTransform,
+                        		isSelected:true,
+                        	}]
+                        }
+                        element.actors.forEach(actor=>{
+                        	let _actorLoaction = actor.actorLocation.split(',');//x y z
+                        	let X_C = parseInt(_actorLoaction[0]);//X轴偏移量-UE原因
+                        	let Y_C = -parseInt(_actorLoaction[1]);//Y轴偏移量-取反,UE里面的Y轴方向跟Three.js相反
+                        	let _x = element.centerX + X_C;
+                        	let _z = -element.centerY + Y_C;//centerY 要取反,因为UE里面是反向的
+                        	
+                        	// let _x = parseInt(_actorLoaction[1]) || element.centerX;//观察点 X轴坐标 
+                        	// let _z = parseInt(_actorLoaction[0]) || element.centerY;//观察点 Z轴坐标
+                        	let _presentX = (_x - element.centerX)/((element.spaceWidth/2) - 10);//10是墙壁厚度-单位cm
+                        	let _presentY = (_z + element.centerY)/((element.spaceHeight/2) - 10);
+                        	//注意如果一开始就设置大超过空间大小,则处理成贴近空间边界
+                        	actor.presentX = Math.abs(_presentX)>1 ? (_presentX>1?1:-1) : _presentX;//观察点跟空间中心原点的距离比例
+                        	actor.presentY = Math.abs(_presentY)>1 ? (_presentY>1?1:-1) : _presentY;
+                        })
 						element.wallMoveValue = "[0,0,0,0]"
                         this.spaceList.push(element);
                         this.wallIds.push(element.wallId);

+ 12 - 2
src/router/index.js

@@ -27,6 +27,8 @@ import webgl_rxdz_test_look from '@/pages/webgl_rxdz_test_look/webgl_rxdz_test_l
 
 import webgl_rxdz_test1_env from '@/pages/webgl_rxdz_test1_env/webgl_rxdz_test1_env';//前测-环境偏好
 
+import webgl_rxdz_test_all from '@/pages/webgl_rxdz_test_all/webgl_rxdz_test_all';//前测-页面包含全部功能
+
 Vue.use(Router)
 const router = new Router({
     mode: 'hash',
@@ -158,8 +160,8 @@ const router = new Router({
 			}
 		},
 		{
-			path: '/pages/webgl_rxdz_test',
-			name: 'webgl_rxdz_test',
+			path: '/pages/webgl_rxdz_test1',
+			name: 'webgl_rxdz_test1',
 			component: webgl_rxdz_test,
 			meta:{
 				keepAlive:true
@@ -205,6 +207,14 @@ const router = new Router({
         		keepAlive:false
         	}
         },
+        {
+        	path: '/pages/webgl_rxdz_test',
+        	name: 'webgl_rxdz_test',
+        	component: webgl_rxdz_test_all,
+        	meta:{
+        		keepAlive:false
+        	}
+        },
     ],
 })
 // router.beforeRouteLeave = (to, from, next)=> {