chenlei hace 8 meses
padre
commit
df6465be4d

+ 287 - 0
public/js/manage.js

@@ -63,6 +63,7 @@ var g_weixinObj = {
 };
 
 var settings = {
+  markerHeight: 0.05,//距离地板高出多少,
   hotClickEvent: {
     video: {
       playAndPause: true,
@@ -1582,6 +1583,290 @@ function initByTHREE(THREE) {
   }
   window.RoomLabel = RoomLabel;
 
+  window.initRouteArrow = ()=>{
+    if(window.isEdit)return
+    
+   
+    
+    
+    
+    if(!window.DATA.route?.data || Object.keys(window.DATA.route.data).length == 0)return
+    
+    let {hide, gradualShow, opacityShine, data={}} = window.DATA.route || {}      //hide 默认是否隐藏,若隐藏也可以通过函数展示
+    
+    let panos = player.model.panos 
+    panos.routeNextMap = {} //下一个
+    panos.routePreMap = {} //上一个
+    panos.list.forEach((pano,i)=>{
+        panos.routePreMap[pano.id] = []  
+        panos.routeNextMap[pano.id] = data[pano.id] ? data[pano.id].map(id=>panos.get(id)) : []   
+    })
+    for(let panoId in data){
+        data[panoId].forEach(id=>{
+            panos.routePreMap[id].push(panos.get(panoId)) 
+        }) 
+    }
+    
+    var arrowInfo = { 
+        animateDur : 5000,
+        showDur: 1000,
+        minOpa: 0.2,
+        maxOpa: 0.5 
+         
+    }
+    
+  
+    let arrowTex = Texture.load('images/arrow.png') 
+        arrowTex.anisotropy = 4
+        
+        
+    let arrowMat = new THREE.MeshBasicMaterial({
+        name: 'arrow',
+        transparent:true,
+        map:arrowTex,
+        side:2,
+        opacity: arrowInfo.maxOpa,
+        //depthTest:false
+        depthWrite:false, //防止和导览路线重叠闪烁
+    }) 
+    let mats = {
+        default: arrowMat,
+        fadeIn: arrowMat.clone()
+    }
+    mats.fadeIn.name = 'fadeInArrow'
+    let plane = new THREE.PlaneBufferGeometry(1,1)
+   
+    
+    let arrows = new THREE.Object3D; arrows.name = 'groundArrows'
+      
+    player.model.add(arrows)
+  
+    
+    var createArrow = function(mat){
+      
+        var arrow = new THREE.Mesh(plane, mat)
+        arrow.name = 'arrow'
+        
+        let s = 0.15
+        arrow.scale.set(s,s,s)
+         
+        arrows.add(arrow)
+        return arrow
+    }
+  
+  
+  
+    
+    
+     
+    
+    var updateArrowPose = function(from, to, mat ){
+         
+        var vec = to.floorPosition.clone().clone().sub(from.floorPosition).setY(0);
+        let spaceDis = 0.4//箭头之间的间距
+        let margin = 0.3 //marker端需要留一点距离
+        let sliceCount = Math.max(2, Math.round((vec.length()-margin) / spaceDis)) //分段  
+        let arrowCount = sliceCount - 1
+        
+        let dir = vec.clone().normalize()
+        let dir2d = new THREE.Vector2(dir.x, dir.z)
+        let angle = dir2d.angle() - Math.PI/2
+        let sliceLen = (vec.length()-margin) / sliceCount 
+        let i = arrowCount
+        
+        while(i>0){
+            
+            let pos = from.floorPosition.clone().add(dir.clone().multiplyScalar(margin/2 + i*sliceLen))
+                pos.y+=settings.markerHeight 
+            let arrow = createArrow(mat)
+                arrow.name = 'arrow:'+from.id+"-"+to.id+"|"+i
+            arrow.rotation.set(Math.PI/2, 0, angle);
+            arrow.position.copy(pos)
+            i--
+        } 
+        
+    }
+     
+    var updateArrowOpacity = function(e){//不停更新所有arrow的透明度
+        var transition = function(a){
+            if(!arrows.visible)return
+            
+            var opa = a > 0.5 ? 2-a*2 : 2*a ;
+            opa = arrowInfo.maxOpa*opa+ arrowInfo.minOpa*(1-opa)
+            
+            mats.default.opacity = opa
+            mats.fadeIn.opacity = opa * mats.fadeIn.opacity2
+                
+        }
+        transitions.start(transition, arrowInfo.animateDur, updateArrowOpacity, 0, easing.easeInOutCubic, "updateArrowOpacity")
+    }
+  
+    var fadeInArrow = function(){
+        
+        transitions.cancelById('updateArrowOpacity2')
+        var arrows_ = arrows.children.filter(e=> e.material == mats.fadeIn)
+        if(arrows_.length == 0)return
+        
+        
+        mats.fadeIn.opacity = 0 
+        
+        var transition = function(a){ 
+            if(!opacityShine) mats.fadeIn.opacity = a * arrowInfo.maxOpa
+            else mats.fadeIn.opacity2 = a
+        } 
+        transitions.start(transition, arrowInfo.showDur, function done(){
+            arrows_.forEach(e=>e.material = mats.default)
+        }, 0, easing.easeInOutCubic, "updateArrowOpacity", "updateArrowOpacity2")
+    }
+  
+    var lastArrowPanos = []
+    var updateArrow = function(){//根据当前pano更新
+        
+        if(player.mode != 'panorama' || hide){ //飞出 
+            arrows.visible = false           
+            lastArrowPanos = []
+            return;
+        }
+        arrows.visible = true
+        let currentPano = player.currentPano
+        
+        
+        //先获取所有需要箭头的pano
+        var maxDistance = 6;//该距离内pano可见箭头
+        var maxPathCount = 8;
+        var dis = 0
+        var curPano = currentPano;
+        var panos_ = [];
+        
+        var getAngle = function(pano1,pano2){
+            let dir = new THREE.Vector3().subVectors(pano1.position,pano2.position)
+            dir = new THREE.Vector2(dir.x, dir.z)
+            return dir.angle()
+        }
+        var search = function(pano, path=[pano], angles=[]){//多分支搜寻
+            
+            var neighbor = panos.routeNextMap[pano.id];
+            if(!neighbor || !neighbor.length)return //path.length>1 && console.log('branchPath',path);
+            
+            
+            neighbor.forEach(e=>{
+                let branchPath = path.slice(), angles_ = angles.slice() 
+                if(panos_.find(arr=>arr[0]==e))return //console.log('不回头branchPath',branchPath); //不回头
+                dis = e.floorPosition.distanceTo(currentPano.floorPosition)
+                
+                branchPath.push(e)
+                if(branchPath.length>2){//不折回,否则感觉在面前饶了一圈回来很难看
+                    let i=0
+                    while(i<branchPath.length-1){ //补全angles
+                        if(angles_[i] == void 0){
+                            angles_[i] = getAngle(branchPath[i], branchPath[i+1]) 
+                        }
+                        i++
+                    }
+                    let lastAngle = angles_[branchPath.length-2]//getAngle(branchPath[i],  e)
+                    let reverse = angles_.find((angle, n)=> {
+                        let angleDiff = Math.abs(( lastAngle - angle) % (Math.PI*2) ) //越远限制越大
+                        let minDiff = math.linearClamp(branchPath.length,[3,6],[0.2,0.5])
+                        if(Math.abs(angleDiff - Math.PI ) < minDiff){
+                            //console.log('因为折回而提前结束', n, branchPath)
+                            return true
+                        } 
+                    })
+                    if(reverse != void 0){
+                        return
+                    } 
+                }
+                
+                
+                if(branchPath.length<3 || dis < maxDistance){
+                    panos_.push([pano, e]) 
+                    search(e, branchPath, angles_)
+                }else{
+                    //console.log('branchPath',branchPath)
+                }
+            })
+            
+        }
+        
+        //search(currentPano)
+        let disMap = new Map, cosMap = new Map
+        let camDir = player.getDirection()
+        let neighbors = currentPano.neighbourUUIDs.map(e=>panos.get(e))
+                        .filter(p=>{
+                            let dir = new THREE.Vector3().subVectors(p.position, currentPano.position)
+                            let d = dir.lengthSq()
+                            if(d < 15){//最大距离
+                                disMap.set(p, d);
+                                cosMap.set(p, dir.normalize().dot(camDir)) 
+                                return true
+                            }
+                        }).sort((a,b)=>{ 
+                            let score = disMap.get(a) - disMap.get(b) 
+                            score += (cosMap.get(b) - cosMap.get(a)) * 5
+                            return score
+                        })//从近到远,尽量在前方
+                        
+        let seedPanos = [currentPano, ...neighbors]//如果没有从当前点出发的箭头,就展示隔壁点的(缺点是隔壁点可能是指向当前点的,原规则是不展示来的路径的,所以会有点奇怪。虽然也可以在search后剔除啦)
+        for(let seed of seedPanos){
+            search(seed)
+            if(panos_.length != 0){
+                break;
+            }
+        }
+         
+        
+        arrows.children.slice().forEach(child=>arrows.remove(child))
+        
+        
+        panos_.forEach((panoArr,i)=>{
+            var isNew = !lastArrowPanos.find(e=>e[0]==panoArr[0] && e[1]==panoArr[1])//新出现的点  渐变出现
+            updateArrowPose(panoArr[0], panoArr[1], isNew ? mats.fadeIn : mats.default )//更新位置
+            
+        })
+        
+        fadeInArrow()
+        
+         
+        
+        lastArrowPanos = panos_
+    }
+  
+    let inited
+    let init = ()=>{
+        if(inited)return
+        if(gradualShow){
+            player.on("flying.ended", updateArrow )  
+        }else{ 
+            //展示全部
+            for(let id1 in panos.routeNextMap){
+                for(let pano2 of panos.routeNextMap[id1]){ 
+                    updateArrowPose(panos.get(id1), pano2, mats.default) 
+                }  
+            } 
+            
+            player.on("mode.changed", ()=>{
+                if(hide)return
+                arrows.visible = player.mode == 'panorama'
+            })
+        }
+        opacityShine && updateArrowOpacity()
+        inited = true
+    }
+     
+    
+    {//ui控制显示
+        let changeShow = (e)=>{ 
+            hide = !e.show 
+            e.show && init()
+            gradualShow ? updateArrow() : (arrows.visible = e.show)
+        }
+        
+        player.on('changeArrowShow',changeShow) 
+        changeShow({show:!hide})
+    }
+    
+  }
+
   let f = () => {
     window.bus.removeEventListener('playerAndModelReady', f);
 
@@ -1606,6 +1891,8 @@ function initByTHREE(THREE) {
     });
 
     player.model.hotGroup.children.length ? logSth() : player.on('gotHotAndStartload', logSth);
+
+    initRouteArrow()
   };
   window.bus.addEventListener('playerAndModelReady', f); //player model currentPano都已有
 

+ 1 - 1
scripts/publish.js

@@ -1,7 +1,7 @@
 import fs from 'fs-extra';
 import ch from 'child_process';
 
-const SCENE = process.env.SCENE;
+const SCENE = process.env.VITE_APP_SCENE;
 
 fs.ensureDirSync('.temp');
 fs.emptyDirSync('.temp');

+ 1 - 1
src/index/views/home/components/menu/index.scss

@@ -125,7 +125,7 @@
 
 .icon-fullscreen:before {
   content: '';
-  background: url('/public/images/enlarge_on.png') center top no-repeat;
+  background: url('/images/enlarge_on.png') center top no-repeat;
   background-size: 100%;
   display: inline-block;
   width: 24px;

+ 1 - 1
src/index/views/home/components/menu/index.syjy.vue

@@ -40,7 +40,7 @@
             title=""
             style="display: none; float: left"
           >
-            <img class="icon icon-inside" src="images/face.jpg" />
+            <img class="icon icon-inside" src="/images/face.jpg" />
           </div>
         </div>
       </div>

+ 1 - 1
src/index/views/home/components/popup/index.scss

@@ -31,5 +31,5 @@
   cursor: pointer;
   text-indent: -999em;
   background-size: 100% 100%;
-  background: url('/public/images/close1.png') no-repeat;
+  background: url('/images/close1.png') no-repeat;
 }

+ 1 - 1
src/index/views/home/components/title/index.scss

@@ -108,7 +108,7 @@
     display: block;
     width: 18px;
     height: 18px;
-    background: url('/public/images/4dage-logo.png') left top no-repeat;
+    background: url('/images/4dage-logo.png') left top no-repeat;
     background-size: 100%;
   }
 }

+ 1 - 1
src/index/views/home/components/title/index.syjy.scss

@@ -108,7 +108,7 @@
     display: block;
     width: 18px;
     height: 18px;
-    background: url('/public/images/4dage-logo.png') left top no-repeat;
+    background: url('/images/4dage-logo.png') left top no-repeat;
     background-size: 100%;
   }
 }

+ 7 - 7
src/index/views/home/index.tsx

@@ -76,18 +76,18 @@ export default defineComponent({
         </div>
 
         {/* TODO: 没有控制权,耦合严重;放在此处为了防止元素未渲染导致报错 */}
-        <JsScript src="/js/manage.js" onLoad={() => (this.manageJsLoaded = true)} />
+        <JsScript src="./js/manage.js" onLoad={() => (this.manageJsLoaded = true)} />
         {this.manageJsLoaded && (
           <div>
-            <JsScript src="/js/Hot.js" onLoad={() => (this.hotJsLoaded = true)} />
+            <JsScript src="./js/Hot.js" onLoad={() => (this.hotJsLoaded = true)} />
             {this.hotJsLoaded && (
               <div>
-                <JsScript src="/js/main_2020_show.js" />
+                <JsScript src="./js/main_2020_show.js" />
                 {/* 延迟加载 */}
-                <JsScript src="/js/lib/player-0.0.12.min.js" />
-                <JsScript src="/js/lib/Tween.js" />
-                <JsScript src="/js/SpecialScene.js" />
-                <JsScript src="/js/loadCAD.js" />
+                <JsScript src="./js/lib/player-0.0.12.min.js" />
+                <JsScript src="./js/lib/Tween.js" />
+                <JsScript src="./js/SpecialScene.js" />
+                <JsScript src="./js/loadCAD.js" />
               </div>
             )}
           </div>

+ 7 - 7
src/index/views/home/index.zgrs.tsx

@@ -83,18 +83,18 @@ export default defineComponent({
         </div>
 
         {/* TODO: 没有控制权,耦合严重;放在此处为了防止元素未渲染导致报错 */}
-        <JsScript src="/js/manage.js" onLoad={() => (this.manageJsLoaded = true)} />
+        <JsScript src="./js/manage.js" onLoad={() => (this.manageJsLoaded = true)} />
         {this.manageJsLoaded && (
           <div>
-            <JsScript src="/js/Hot.js" onLoad={() => (this.hotJsLoaded = true)} />
+            <JsScript src="./js/Hot.js" onLoad={() => (this.hotJsLoaded = true)} />
             {this.hotJsLoaded && (
               <div>
-                <JsScript src="/js/main_2020_show.js" />
+                <JsScript src="./js/main_2020_show.js" />
                 {/* 延迟加载 */}
-                <JsScript src="/js/lib/player-0.0.12.min.js" />
-                <JsScript src="/js/lib/Tween.js" />
-                <JsScript src="/js/SpecialScene.js" />
-                <JsScript src="/js/loadCAD.js" />
+                <JsScript src="./js/lib/player-0.0.12.min.js" />
+                <JsScript src="./js/lib/Tween.js" />
+                <JsScript src="./js/SpecialScene.js" />
+                <JsScript src="./js/loadCAD.js" />
               </div>
             )}
           </div>