xzw 4 년 전
부모
커밋
0b5e249cbb
7개의 변경된 파일623개의 추가작업 그리고 5437개의 파일을 삭제
  1. 46 19
      edit-backstage/css/lzb.css
  2. 26 12
      edit-backstage/edit.html
  3. 0 252
      edit-backstage/js/css/cropper.min.css
  4. 0 3241
      edit-backstage/js/css/edit.js
  5. 0 1788
      edit-backstage/js/css/lzb.css
  6. 204 59
      edit-backstage/js/edit.js
  7. 347 66
      edit-backstage/js/main_2020_edit.js

+ 46 - 19
edit-backstage/css/lzb.css

@@ -895,28 +895,12 @@ ul.MenuOptions li.chosen {
 
 .toolBottom .midBottom {
     width: 100%;
-    height: 93px;
+    height: 98px;
     position: relative;
 }
 
 .confirmSnap {
-    background: #00b4ed;
-    color: #fff;
-    border-radius: 21px;
-    /* margin: 0 auto; */
-    position: absolute;
-    letter-spacing: 0.05em;
-    height: 42px;
-    text-align: center;
-    line-height: 42px;
-    font-size: 14px;
-    pointer-events: all;
-    cursor: pointer;
-    transition: background 0.2s;
-    top: 8px;
-    width: 220px;
-    left: 50%;
-    transform: translateX(-50%);
+     
 }
 
 #webgl .overlayGui.snapshotGui {
@@ -1165,6 +1149,36 @@ ul.MenuOptions li.chosen {
 }
 
 
+
+#midBtns{
+    position: absolute;
+    transform: translateX(-50%);
+    width: 220px;
+    left: 50%;
+    flex-direction: column;
+}
+#midBtns>*{
+    /* color: #fff; */
+    border-radius: 21px;
+    /* margin: 0 auto; */
+    margin: 0px 0 0 0 !important;
+    letter-spacing: 0.05em;
+    height: 38px;
+    text-align: center;
+    line-height: 42px;
+    font-size: 14px;
+    pointer-events: all;
+    cursor:pointer;
+    transition:background 0.2s;
+    width: 220px;
+}
+
+#midBtns button:nth-child(2) {
+    margin: 10px 0 0 0 !important;
+}
+
+
+
 .toolRight  .itemTitle .buttons, .toolRight .remark .buttons{
    position:absolute; right:0;
     
@@ -1227,10 +1241,11 @@ ul.MenuOptions li.chosen {
     color: #fff;
     text-align: center;
     position: relative;
-    display: inline-block;
+    display: block;
     line-height: 90px;
     font-size: 30px;
     font-weight: 300;
+    box-sizing: content-box;
 }
 
 .edit-fun-images a.result>span::after {
@@ -1255,6 +1270,18 @@ ul.MenuOptions li.chosen {
     max-height: 100%;
 }
 
+.edit-fun-images a .play-video{
+    position:absolute;
+    transform: translate(50%,50%); 
+    left: 0; top: 0;
+    opacity:0.3;
+    transition:opacity 0.2s;
+}
+.edit-fun-images a .play-video:hover{
+    opacity:1
+}
+
+
 .edit-fun-images .upload-thum {
     display: block;
     position: relative;

+ 26 - 12
edit-backstage/edit.html

@@ -893,8 +893,11 @@
                 </div>
                 <div class="midBottom hasPad">
                     <!-- 中间下部 -->
-                    <div class="confirmSnap innerBtn hide" id="camera-start">点此设置为初始画面</div>
-                    <!--  <div class="innerBtn hide cancel" data-lang="">隐藏该点</div>  -->
+                    <div id="midBtns" class="buttons">
+						<button class="confirmSnap hide innerBtn" id="camera-start">保存当前设置</button> 
+						<button class="innerBtn hide cancel" function="hide">隐藏该点位置</button> 				 
+                    
+                    </div>
                 </div>
             </div>
             <div class="toolRight">
@@ -918,7 +921,7 @@
                                 </label>
                             </ul>
                         </li> -->
-                        <li data-name="MouseMarkerColor" class="tourSelectWarp hotListSwitch">
+                        <li class="tourSelectWarp hotListSwitch">
                             <div class="itemTitle">
                                 <span>热点大小 (初始值为1)</span>
                             </div>
@@ -955,10 +958,10 @@
                                         <input spellcheck="false" placeholder="热点的标题" class="right" type="text"
                                             minlength="1" maxlength="50" placeholder="">
                                     </div><!-- 必填,限15字 ??-->
-                                    <div class="itemTitle" data-size="500">
+                                    <div class="itemTitle" data-size="800">
                                         <span>简介</span>
                                     </div>
-                                    <textarea placeholder="热点的简介" class="editText" maxlength="500"></textarea>
+                                    <textarea placeholder="热点的简介" class="editText" maxlength="800"></textarea>
 
 
 
@@ -1198,13 +1201,13 @@
                             <!-- <div class="unComplete">请填写项目名称</div> -->
                         </li>
                         <li data-name="description">
-                            <div class="itemTitle" data-size="200" id="project-intro2">
+                            <div class="itemTitle" data-size="1000" id="project-intro2">
                                 <span>简介内容</span>
                             </div>
 
                             <textarea placeholder="大场景的简介" id="info-summary" class="editText"
-                                maxlength="200"></textarea>
-
+                               maxlength="1000"  ></textarea>
+                            
                             <!-- <div class="itemTitle" data-size="200" id="project-intro2">
                                 <span>分享文字</span>
                             </div>
@@ -1409,11 +1412,12 @@
                                         <div class="itemTitle">
                                             <span>选择导览过渡效果</span>
                                         </div>
-                                        <ul id="folderTourSwitch" class="switch clearfix hotStyle-item colorWrap">
-                                            <label><input class="mui-switch mui-switch-animbg" type="checkbox">
-                                                启用瞬间过渡
-                                            </label>
+                                        <ul id="folderTourSwitch"  class="MenuOptions innerBtn" >
+                                            <li class="halfCell" index="default" data-lang="">同外层</li>
+                                            <li class="halfCell" index="walk" data-lang="">行走</li>
+                                            <li class="halfCell chosen" index="black" data-lang="">瞬间</li>
                                         </ul>
+                                        
                                     </li>
                                     <li class="snapATourView">
                                         <div class="buttons begin">
@@ -1472,6 +1476,16 @@
                                             </div>
                                         </div>
                                     </li>
+                                    <li>
+                                        <div class="itemTitle">
+                                            <span>飞向该片段的过渡效果</span>
+                                        </div> 
+                                        <ul id="tourSwitch_Slice"  class="MenuOptions innerBtn" >
+                                            <li class="halfCell" index="default" data-lang="">同外层</li>
+                                            <li class="halfCell" index="walk" data-lang="">行走</li>
+                                            <li class="halfCell chosen" index="black" data-lang="">瞬间</li>
+                                        </ul>  
+                                    </li>
                                     <li id="tourRenew" class="info"> 
                                         <div class="name itemMargin">
                                             <div class="buttons begin">

+ 0 - 252
edit-backstage/js/css/cropper.min.css

@@ -1,252 +0,0 @@
-/*!
- * Cropper v3.1.3
- * https://github.com/fengyuanchen/cropper
- *
- * Copyright (c) 2014-2017 Chen Fengyuan
- * Released under the MIT license
- *
- * Date: 2017-10-21T10:03:37.133Z
- */.cropper-container {
- direction:ltr;
- font-size:0;
- line-height:0;
- position:relative;
- -ms-touch-action:none;
- touch-action:none;
- -webkit-user-select:none;
- -moz-user-select:none;
- -ms-user-select:none;
- user-select:none
-}
-.cropper-container img {
- display:block;
- height:100%;
- image-orientation:0deg;
- max-height:none!important;
- max-width:none!important;
- min-height:0!important;
- min-width:0!important;
- width:100%
-}
-.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box {
- bottom:0;
- left:0;
- position:absolute;
- right:0;
- top:0
-}
-.cropper-canvas,.cropper-wrap-box {
- overflow:hidden
-}
-.cropper-drag-box {
- background-color:#fff;
- opacity:0
-}
-.cropper-modal {
- background-color:#000;
- opacity:.5
-}
-.cropper-view-box {
- display:block;
- height:100%;
- outline-color:rgba(51,153,255,.75);
- outline:1px solid #39f;
- overflow:hidden;
- width:100%
-}
-.cropper-dashed {
- border:0 dashed #eee;
- display:block;
- opacity:.5;
- position:absolute
-}
-.cropper-dashed.dashed-h {
- border-bottom-width:1px;
- border-top-width:1px;
- height:33.33333%;
- left:0;
- top:33.33333%;
- width:100%
-}
-.cropper-dashed.dashed-v {
- border-left-width:1px;
- border-right-width:1px;
- height:100%;
- left:33.33333%;
- top:0;
- width:33.33333%
-}
-.cropper-center {
- display:block;
- height:0;
- left:50%;
- opacity:.75;
- position:absolute;
- top:50%;
- width:0
-}
-.cropper-center:after,.cropper-center:before {
- background-color:#eee;
- content:" ";
- display:block;
- position:absolute
-}
-.cropper-center:before {
- height:1px;
- left:-3px;
- top:0;
- width:7px
-}
-.cropper-center:after {
- height:7px;
- left:0;
- top:-3px;
- width:1px
-}
-.cropper-face,.cropper-line,.cropper-point {
- display:block;
- height:100%;
- opacity:.1;
- position:absolute;
- width:100%
-}
-.cropper-face {
- background-color:#fff;
- left:0;
- top:0
-}
-.cropper-line {
- background-color:#39f
-}
-.cropper-line.line-e {
- cursor:e-resize;
- right:-3px;
- top:0;
- width:5px
-}
-.cropper-line.line-n {
- cursor:n-resize;
- height:5px;
- left:0;
- top:-3px
-}
-.cropper-line.line-w {
- cursor:w-resize;
- left:-3px;
- top:0;
- width:5px
-}
-.cropper-line.line-s {
- bottom:-3px;
- cursor:s-resize;
- height:5px;
- left:0
-}
-.cropper-point {
- background-color:#39f;
- height:5px;
- opacity:.75;
- width:5px
-}
-.cropper-point.point-e {
- cursor:e-resize;
- margin-top:-3px;
- right:-3px;
- top:50%
-}
-.cropper-point.point-n {
- cursor:n-resize;
- left:50%;
- margin-left:-3px;
- top:-3px
-}
-.cropper-point.point-w {
- cursor:w-resize;
- left:-3px;
- margin-top:-3px;
- top:50%
-}
-.cropper-point.point-s {
- bottom:-3px;
- cursor:s-resize;
- left:50%;
- margin-left:-3px
-}
-.cropper-point.point-ne {
- cursor:ne-resize;
- right:-3px;
- top:-3px
-}
-.cropper-point.point-nw {
- cursor:nw-resize;
- left:-3px;
- top:-3px
-}
-.cropper-point.point-sw {
- bottom:-3px;
- cursor:sw-resize;
- left:-3px
-}
-.cropper-point.point-se {
- bottom:-3px;
- cursor:se-resize;
- height:20px;
- opacity:1;
- right:-3px;
- width:20px
-}
-@media (min-width:768px) {
- .cropper-point.point-se {
-  height:15px;
-  width:15px
- }
-}
-@media (min-width:992px) {
- .cropper-point.point-se {
-  height:10px;
-  width:10px
- }
-}
-@media (min-width:1200px) {
- .cropper-point.point-se {
-  height:5px;
-  opacity:.75;
-  width:5px
- }
-}
-.cropper-point.point-se:before {
- background-color:#39f;
- bottom:-50%;
- content:" ";
- display:block;
- height:200%;
- opacity:0;
- position:absolute;
- right:-50%;
- width:200%
-}
-.cropper-invisible {
- opacity:0
-}
-.cropper-bg {
- background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")
-}
-.cropper-hide {
- display:block;
- height:0;
- position:absolute;
- width:0
-}
-.cropper-hidden {
- display:none!important
-}
-.cropper-move {
- cursor:move
-}
-.cropper-crop {
- cursor:crosshair
-}
-.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point {
- cursor:not-allowed
-}
-/*# sourceMappingURL=cropper.min.css.map */

파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 3241
edit-backstage/js/css/edit.js


파일 크기가 너무 크기때문에 변경 상태를 표시하지 않습니다.
+ 0 - 1788
edit-backstage/js/css/lzb.css


+ 204 - 59
edit-backstage/js/edit.js

@@ -76,6 +76,11 @@ EditTools.prototype.init = function() {
         $(".DelConfirm").removeClass("active");
     })
 
+    $(" .MenuOptions li").on("click", (e)=>{ 
+        var $elem = $(e.target);
+        $elem.closest('.MenuOptions').find('li').removeClass("chosen");
+        $elem.addClass("chosen"); 
+    })
 }
 //点击的时候激活状态
 EditTools.prototype.active = function() {
@@ -151,10 +156,10 @@ EditTools.prototype.initSaveAll = function() {
         $(".edit-loading").removeClass("hide");
  
 
-        var $images = $(".information .edit-fun-images a.result");
+        var $shareImages = $(".information .edit-fun-images a.result");
 
-        new Promise(function(resolve, reject) {
-            upload($images, 'images', resolve)
+        new Promise(function(resolve, reject) {//分享图
+            upload($shareImages, 'images', resolve)
         }).then(function(imgUrls) {
             
             //导览的数据
@@ -724,13 +729,14 @@ Hotpoint.prototype.editHot = function(hot, $li) {
     .bind(this))
 
     var imagesHTML = info.images.map(function(image) {
-        return '<div><a class=" result success"><span></span><img src="' + image + '"></a></div>'
+        return '<div><a class=" result success" data-type="photo"><span></span><img src="' + image + '" class="bg"></a></div>'
     })
 
     var videosHTML = info.video.map(function(ly) {
-        var imgDom = (!ly.img || ly.img === "undefined") ? '' : 'success';
-        var imgUrl = (!ly.img || ly.img === "undefined") ? playIcon : ly.img;
-        return '<div><a class=" result success"><span></span><img class="play-video" videoURL="' + ly.url + '" src="' + imgUrl + '"></a  ><span class="upload-thum ' + imgDom + ' result" attr-thum="' + ly.img + '">上传封面<i><input type="file"></i></span></div>'
+        var thumb = (!ly.img || ly.img === "undefined") ? '' : '<img src='+ ly.img +' class="bg"></img>'
+        var thumbResult = (!ly.img || ly.img === "undefined") ? '' : 'success';
+        var dom = '<div><a class=" result success" data-type="video"><span></span>' + thumb + ' <img class="play-video" videoURL="' + ly.url + '" src="' + playIcon + '"></a>  <span class="upload-thum ' + thumbResult + ' result" attr-thum="' + ly.img + '">上传封面<i><input type="file" accept="image/*"></i></span></div>'
+        return dom
     })
 
     this.hotpointDetail.find(".name > input").val(info.title);
@@ -789,13 +795,13 @@ Hotpoint.prototype.addmedia = function() {
             return false;
         }
 
-        $elayout.append('<span class="upload-thum">上传封面<i><input type="file"></i></span>')
+        $elayout.append('<span class="upload-thum">上传封面<i><input type="file" accept="image/*"></i></span>')
 
         return '<img src="./images/play.png" class="play-video" videoURL="' + URL.createObjectURL(file) + '">'
     }
 
     // 视频封面回调
-    function thumSuccess(file, $elayout, $seft) {
+    function thumbSuccess(file, $elayout, $seft) {
         if (!/image\/\w+/.test(file.type)) {
             alert("文件必须为图片!");
             return false;
@@ -804,34 +810,60 @@ Hotpoint.prototype.addmedia = function() {
             return false;
         }
 
-        $seft.closest('div').find('img').attr('src', URL.createObjectURL(file));
+        var img = $seft.closest('div').find('img.bg');
+        if(!img[0]){
+            img = $("<img class='bg'></img>");
+            $seft.closest('div').find('a').append(img)
+        }
+        img.attr('src', URL.createObjectURL(file));
+        $seft.closest('span').removeClass("success")
+         
     }
 
     // 图片与视频加载
     function fileHandle() {
-        var $seft = $(this)
-        var $layout = $seft.closest("li");
-        var type = $seft.parent().attr('data-type');
+        var $seft = $(this) //input
+        
+         
         var file = this.files[0];
+        var type = this.activeElem ? this.activeElem.attr('data-type') : $seft.parent().attr('data-type');
+        
         var $din = $(document.createElement('div'));
-        var fnc = type === 'photo' ? imageSuccess : type === 'video' ? videoSuccess : thumSuccess
+        var fnc = type === 'photo' ? imageSuccess : type === 'video' ? videoSuccess : thumbSuccess //再次传都会是thumSuccess
         var $dom = fnc(file, $din, $seft)
 
         if (type === 'photo' || type === 'video') {
             if (!$dom)
                 return $seft.val('');
-            var $addLayout = $(document.createElement('a'));
-            var $addInput = $('<input type="file">')
-            var $close = $(document.createElement('span'));
-            $addInput[0].files = this.files;
-            $addLayout.append($addInput)
-            $addLayout.append($close);
-            $addLayout.append($dom);
-            $addLayout.addClass("result");
-            $din.prepend($addLayout);
-            $layout.find('.edit-fun-images').append($din);
+            
+            if(!this.activeElem){//创建新的item
+                var $layout = $seft.closest("li"); 
+                var $addLayout = $(document.createElement('a'));
+                $addLayout.attr("data-type", type)
+                 
+                var $close = $(document.createElement('span'));
+                 
+                $addLayout[0].file = file;
+                
+                $addLayout.append($close);
+                $addLayout.append($dom);
+                $addLayout.addClass("result");
+                $din.prepend($addLayout);
+                $layout.find('.edit-fun-images').append($din);
+            }else{//重传
+                if (type === 'photo'){
+                    this.activeElem.find("img.bg").remove();
+                }else{
+                    this.activeElem.find(".play-video").remove();
+                }
+                this.activeElem.removeClass("success")  
+                this.activeElem.append($dom)
+                this.activeElem[0].file = file;
+                this.value = ''
+            }  
         }
 
+
         if (searchParent($seft[0], {
             id: 'shareImgUpload'
         })) {
@@ -844,6 +876,9 @@ Hotpoint.prototype.addmedia = function() {
          */}
 
     }
+    //用于重传的input
+    var imgInput = $("<input accept='image/*'  type='file'></input>")
+    var videoInput = $("<input accept='video/*' type='file'></input>")
     ;// 图片与视频加载
     $('.upload, .edit-fun-images').on('change', function(ev) {
         if (ev.target.tagName.toUpperCase() === 'INPUT') {
@@ -851,24 +886,44 @@ Hotpoint.prototype.addmedia = function() {
         }
 
     })
-    $('.edit-fun-images').on('click', function(ev) {
+    imgInput.on('change', (ev)=>{fileHandle.call(ev.target)})
+    videoInput.on('change', (ev)=>{fileHandle.call(ev.target)})
+    
+    $('.edit-fun-images').on('click', function(ev) {//点击item时
         var $tag = $(ev.target)
         var tagName = ev.target.tagName.toUpperCase()
         if (tagName === 'SPAN') {
-            var $resf = $(ev.target)
-            if (searchParent($resf[0], {
+            
+            if (searchParent($tag[0], {
                 className: 'forShareImg'
             })) {
                 //信息页面的分享图片
                 $("#shareImgUpload").removeClass('hide')
-            /* }else if(searchParent($resf[0], {
+            /* }else if(searchParent($tag[0], {
                     className: 'SpotStyle'
                 })){
                 $("#SpotStyle").removeClass('hide')
              */}
-            $resf.parent().parent().remove()
+            $tag.parent().parent().remove()
         } else if (tagName === 'IMG' && $tag.hasClass('play-video')) {
             $videoLayout.css('display', 'flex').find('video').attr('src', $tag.attr('videoURL'))[0].play()
+                    }else{// 替换
+            var a = searchParent($tag[0], {
+                tagName: 'a'
+            })
+            if(a) {
+                var input  
+                if(searchParent($tag[0], {
+                    className: 'video'
+                })){
+                    input = videoInput 
+                }else{
+                    input = imgInput
+                    
+                }
+                input[0].activeElem = $(a)
+                input.click()
+            }  
         }
     })
 }
@@ -891,8 +946,7 @@ $("#hotpointDetail .style .MenuOptions li").on("click", (e)=>{
     } else {
         $("#userUploadStyle").removeClass("hide")
     }
-    $("#hotpointDetail .style .MenuOptions li").removeClass("chosen");
-    $(e.target).addClass("chosen")
+    
 }
 )
 
@@ -1141,13 +1195,13 @@ Hotpoint.prototype.initSaveHot = function() {
             )
         }).then(function(videoUrls) {
             args.video = videoUrls
-            //获取热点视频图片所有的路径
+            //获取视频封面路径
             return new Promise(function(resolve, reject) {
                 upload($thums, 'images', resolve)
             }
             )
         }).then(function(thums) {
-            args.video = args.video.map(function(video, index) {
+            args.video = args.video.map(function(video, index) {//整合视频+封面
                 return {
                     url: video,
                     img: thums[index]
@@ -1279,12 +1333,7 @@ Hotpoint.prototype.initSaveHot = function() {
 
     })
     
-    $(".webPage .MenuOptions li").on("click", (e)=>{ //链接打开方式切换 
-        _this.editSpot.linkType = $(e.target).attr("index") 
-        $(".webPage .MenuOptions li").removeClass("chosen");
-        $(e.target).addClass("chosen")
-        
-    })
+    
     
     $("#noAction").on("change", function(e) {
         _this.editSpot.noAction = this.checked;
@@ -1727,7 +1776,11 @@ EditGuide.prototype.editFolder = function(folderDom){
     
     $("#tourFolderEdit").removeClass('atRight');
     $("#tourFolderEdit .tourName input").val( $(folderDom).find('.title').text()||'');
-    $("#folderTourSwitch input").prop('checked', folderDom.tourData.momentTour === 'black');
+    //$("#folderTourSwitch input").prop('checked', folderDom.tourData.momentTour === 'black');
+    
+    var momentTour = folderDom.tourData.momentTour || "default"
+    $("#folderTourSwitch li").removeClass('chosen')
+    $("#folderTourSwitch li[index="+ momentTour +"]").addClass('chosen');
     
     folderDom.tourItemDoms.forEach(li=>{
         $("#tourItemList>ul").append(li)
@@ -1757,6 +1810,10 @@ EditGuide.prototype.editFolder = function(folderDom){
 }
  
 
+
+
+
+
 /**
  * @author fyz 编辑单个导览item
  * @param {any} target 所点击的导览点
@@ -1771,6 +1828,23 @@ EditGuide.prototype.editItem = function(li) {
     $('#tourItemEdit').removeClass('atRight');
     $('#tourItemEdit .tourName input').val( $(li).find('.guide-name').text() );
     
+    var momentTour = li.tourData.momentTour || "default"
+    $("#tourSwitch_Slice li").removeClass('chosen')
+    $("#tourSwitch_Slice li[index="+ momentTour +"]").addClass('chosen');
+    
+    var metadata = JSON.parse(li.tourData.metadata);
+    if(metadata.scan_id != 'outside'){
+        var pano = player.model.panos.index[metadata.scan_id]
+        if(pano){ 
+            var q = new THREE.Quaternion().copy(metadata.camera_quaternion);
+            var lookAtPoint = new THREE.Vector3(0,0,-1).applyQuaternion(q).add(pano.position);
+            player.flyToPano({
+                pano: pano,
+                lookAtPoint: lookAtPoint,
+                zoomLevel: metadata.zoom
+            })
+        }
+    }
     
     if(!this.editingFolderLi){//在外的item, 可以上传音乐
         $('#tourItemEdit .mediaUpload').removeClass('hide')
@@ -1801,7 +1875,11 @@ EditGuide.prototype.completeFolder = function(){//点击完成
     
     var tourName = $('#tourFolderEdit .tourName input').val() //|| this.targetTourPoint.context.innerText;
     $(this.editingFolderLi).find(".title").text(tourName) 
-    this.editingFolderLi.tourData.momentTour = $("#folderTourSwitch input").is(':checked') ? "black" : 'walk' 
+    //this.editingFolderLi.tourData.momentTour = $("#folderTourSwitch input").is(':checked') ? "black" : 'walk' 
+    
+    var momentTour = $("#folderTourSwitch li.chosen").attr("index"); 
+    this.editingFolderLi.tourData.momentTour = momentTour != 'default' ?  momentTour : null;
+    
     this.editingFolderLi.tourItemDoms = Array.from($('#tourItemList ul li'));
      
     var done = ()=>{
@@ -1866,8 +1944,9 @@ EditGuide.prototype.completeItem = function() {//点击完成
     var tourName = $('#tourItemEdit .tourName input').val()  
     $(this.editingItemLi).find('.guide-name').text(tourName)
      
+    var momentTour = $("#tourSwitch_Slice li.chosen").attr("index"); 
     
-    
+    this.editingItemLi.tourData.momentTour = momentTour != 'default' ?  momentTour : null;
     //save导览音乐 
     var tourAudio = $('#tourItemEdit .mediaUpload input');
     //判断当前编辑的导览点位是否已上传音乐
@@ -2178,12 +2257,12 @@ function upload($files, type, cb) {
         //attr-thum 属性是视频的图片
         //videoURL 是判断是否有视频
         var $file = $(dFile)
-        var $image = $file.find('img')
+        var $image = type == 'videos' ? $file.find('img.play-video') : $file.find('img')
 
-        if ($file.hasClass('success')) {
-            if ($file.attr('attr-thum')) {
+        if ($file.hasClass('success')) {//已经上传过,有链接
+            if ($file.attr('attr-thum')) {//视频的封面
                 result[index] = $file.attr('attr-thum')
-            } else if ($image.attr('videoURL')) {
+            } else if ($image.attr('videoURL')) {//视频
                 result[index] = $image.attr('videoURL')
             } else {
                 result[index] = $image.attr('src')
@@ -2197,8 +2276,9 @@ function upload($files, type, cb) {
             case "span":
                 dFile = $file.find('input')[0];
                 break;
-            case "a":
-                dFile = $file.find('input')[0];
+            case "a"://重传的图or视频
+                dFile = {files:[$file[0].file]}
+                //dFile = $file.find('input')[0];
                 break;
             default:
                 dFile = $file.closest("li").find('.upload input')[0];
@@ -2867,8 +2947,7 @@ var initTransformCtl = function(THREE) {
 
     $(".MenuOptions[name='transform'] li").on("click", (e)=>{
         transformControls.transCtlChangeMode($(e.target).attr("index"))
-    }
-    )
+    })
 
 }
 
@@ -3435,6 +3514,7 @@ var VisiSet = {
 
     //热点可见性
     $confirmSnap: $("#camera-start"),
+    changeBtn : $(".toolMid .midBottom #midBtns>button").eq(1),
     colors: {
         green: "#00c8ae"
     },
@@ -3444,8 +3524,65 @@ var VisiSet = {
         player.model.add(this.meshGroup)
         $("#hotVisible").on("click", ()=>{
             VisiSet.enterSet(VisiSet.beginSetTagVisible.bind(VisiSet))
-        }
-        )
+            
+        })
+        
+        this.changeBtn.on("click",()=>{//隐藏与显示该点
+            if(this.changeBtn.attr("function") == "hide"){
+                for(let i in this.panoVLines){
+                    this.panoVLines[i].visible && this.dealPanoVisible(i);
+                } 
+            }else{
+                //显示该点时,显示周围一定距离内、到该点没有遮挡的pano
+                //????? 
+                var list = player.model.panos.sortByScore([], [(pano)=>{return -pano.position.distanceTo(this.panoVsetting.position)}])	
+               
+               
+                var length=0 
+				if(list.length == 1){
+					//objects.gui.showInfo('仅有一个漫游点')
+					return;
+				} 
+               
+                
+				var s = Math.max(-list[1].score*1.5,   4);	//i==1的一定显示
+                for(var i=1;i<list.length;i++){
+                    if(!list[i].pano.isAligned())continue;
+                    if(-list[i].score < s){ 
+                    
+						if(length>0){
+							var A = this.panoVsetting.position.clone();
+							var B = list[i].pano.position.clone();
+                             
+                            if (convertTool.ifIntersectChunks(A, B, {}))  continue  
+                            
+                    
+						}		 
+                    
+                        this.dealPanoVisible(list[i].pano.id);
+                        length ++;
+                        //console.log()
+                    }else if(length==1){//少于2个
+                        var lastPos = list[i-1].pano.position.clone().sub(this.panoVsetting.position).setY(0);
+                        var thisPos = list[i].pano.position.clone().sub(this.panoVsetting.position).setY(0);
+                        if(lastPos.angleTo(thisPos) > Math.PI / 2){
+                            console.log('再加一个  角度'+THREE.Math.radToDeg(lastPos.angleTo(thisPos)))
+                            this.dealPanoVisible(list[i].pano.id);
+                        } 
+                        break;
+                    }else{
+                        break;
+                    }
+                }
+                
+                 
+                console.log(list)
+                
+            } 
+        }) 
+        
+    
+        
     },
     enterSet: function(fun) {
         var enter = function() {
@@ -3507,6 +3644,7 @@ var VisiSet = {
         this.createPanoVisiLines(pano);
         //创线
 
+        this.changeBtn.removeClass('hide')
     },
 
     saveLastPanoVi: function() {
@@ -3600,7 +3738,7 @@ var VisiSet = {
         this.panoVsetting = null;
         lastPanoSetting && this.changeFIconState2(lastPanoSetting.footIcon, this.checkHasNeighbor(lastPanoSetting))
         //这句要放在this.panoVsetting = null后。 根据可见性更改透明度
-
+        this.changeBtn.addClass('hide')
     },
 
     //按理说改变了neighbourPano,tag的初始visible也要改。但是这样还要考虑已经改过的tag。。很麻烦
@@ -3629,6 +3767,10 @@ var VisiSet = {
         
     },
 
+    changeVisiBtnState: function(state){ 
+        this.changeBtn.attr("function", state ? "hide" : "show")
+        this.changeBtn.html(state ? "隐藏该点位置":"显示该点位置") 
+    },
     recoverAllState2: function() {
         //为了热点可视恢复成pano全部可见
         if(!this.footIcons)return;
@@ -3804,12 +3946,14 @@ var VisiSet = {
 
     setDisplay: function(state) {
         var panos = player.model.panos;
+  
         if (state) {
-             
+            this.$confirmSnap.text('保存当前设置');
+            this.$confirmSnap.removeClass('hide');
         } else {
-            
+            this.$confirmSnap.addClass('hide');
+            this.changeBtn.addClass('hide')
         }
- 
         player.path.currentPanoMarker.mesh.visible = !state;
         player.overlayGroup.visible = !state;
         player.reticule.visible = !state;
@@ -4015,7 +4159,8 @@ var VisiSet = {
             if (this.panoVsetting) {
                 if (this.panoVsetting.id != footIcon.name) {
                     footIcon.material.uniforms.opacity.value = 1;
-                } else {//this.changeVisiBtnState(true)
+                } else {
+                    this.changeVisiBtnState(true)
                 }
             }
         } else {
@@ -4027,7 +4172,7 @@ var VisiSet = {
             } else {
                 //变为中心点时
                 footIcon.material.uniforms.opacity.value = 1;
-                //this.changeVisiBtnState(false)
+                this.changeVisiBtnState(false)
             }
         }
     },
@@ -4306,7 +4451,7 @@ function searchParent(searchArea, o, maxTimes) {
             return dom
         else if (o.className && dom.classList && dom.classList.contains(o.className))
             return dom
-        else if (o.tagName && o.tagName == dom.tagName)
+        else if (o.tagName && dom.tagName && o.tagName.toUpperCase() == dom.tagName.toUpperCase())
             return dom
     }
     var find;

+ 347 - 66
edit-backstage/js/main_2020_edit.js

@@ -19,7 +19,198 @@ var getVisiblePano = function(position, options={}){
     return visiblePanos
 } 
   
+var convertTool = { 
+	getPos2d : function(point, camera, dom){//获取一个三维坐标对应屏幕中的二维坐标
+		var camera = camera || player.camera;
+		var dom = dom || player.domElement;
+		var pos = point.clone().project(camera)	//比之前hotspot的计算方式写得简单  project用于3转2(求法同shader); unproject用于2转3 :new r.Vector3(e.x, e.y, -1).unproject(this.camera);
+		
+		var x,y;
+		x = (pos.x + 1) / 2 * dom.clientWidth;
+		y = (1 - (pos.y + 1) / 2) * dom.clientHeight; 
   
+		var inSight = x <= dom.clientWidth &&  x >= 0    //是否在屏幕中   
+					&& y <= dom.clientHeight &&  y >= 0 
+	 
+	
+		return {
+			pos: new THREE.Vector2(x,y),  // 屏幕像素坐标
+			vector:  pos,   //(范围 -1 ~ 1)
+			trueSide : pos.z<1, //trueSide为false时,即使在屏幕范围内可见,也是反方向的另一个不可以被渲染的点   参见Tag.update
+			inSight : inSight	//在屏幕范围内可见
+		};
+	},
+
+	ifShelter: function(pos3d, pos2d){//检测某点在视线中是否被mesh遮挡
+		if(!pos2d) pos2d = this.getPos2d(pos3d);
+		var player = player;
+		var ori = new THREE.Vector3(pos2d.x, pos2d.y, -1).unproject(player.camera);  //找到视线原点
+		var dir = pos3d.clone().sub(ori).normalize();
+		ray.set(ori, dir)//由外向里 因为模型从内侧是可见的所以从外侧
+		
+		
+		/* if(config.isEdit && publicObjectSet.editor.mainDesign.editing){
+			var o = ray.intersectObjects(publicObjectSet.editor.mainDesign.wallMeshes);
+		}else{ */
+			var o = ray.intersectObjects(player.model.colliders);
+		//} 
+		var len = pos3d.distanceTo(ori);
+		if (o && o.length) {
+			for(var i=0;i<o.length;i++){
+				if(o[i].distance < len){  return true;  }//有遮挡
+			} 
+		} 
+	},
+    
+    
+    /* 
+        拖拽时,获取鼠标在拖拽面上的位置(需要借助另一个intersectPlane面来计算,即和相机方向一样的面,可保证铺满屏幕)
+        但是不一定能获取到,比如鼠标射线不朝向拖拽面时,即使获取也会是一个意外的反方向的交点。
+	 */
+	getPosAtPlane : function(pos, info/* , mouse, camera */){ //pos:与intersectPlane的交点 见笔记
+		var A = pos; 
+        var player = player;      
+        var mouse = player.mouse;
+        var O = new THREE.Vector3(mouse.x, mouse.y, -1).unproject(player.camera);
+		
+		
+		if(info.y != void 0){//地面线的
+        
+            var y = info.y; 
+            
+            if(player.mode == "floorplan"/*  ||  Math.abs(O.x-pos.x)<0.0001 && Math.abs(O.z-pos.z)<0.0001) */){
+            //intersectPlane和地面平行,无交点
+                var x = pos.x, z = pos.z;
+            
+            }else{
+             
+                if(y<player.camera.position.y && O.y <= A.y /* || y>player.camera.position.y && O.y >= A.y  */)return null;  //鼠标射线向上。因为相机一定位于地面以上(地面不会抬高到相机上吧?),所以无交点。
+                if(O.y == A.y){console.log('一样??');return;}
+                if(A.y == y){console.log('一样2??');return;}
+                var r = (O.y-y)/(A.y-y);
+                var x = (r*A.x-O.x)/(r-1);
+                var z = (r*A.z-O.z)/(r-1); 
+			}
+		}else{//垂直的也有越过消失点以后反向变化的情况,但使用时影响不大
+			var N = info.normalVec;
+			var P = info.pullPos;
+			if(N.y != 0 ){console.log('N.y != 0');return;} //仅仅支持垂直于地面的的墙壁,目前都是
+			if(O.z==A.z){console.log('O.z==A.z?');return;}
+			if(N.z!=0 && N.x != 0){//直接用这个通用的也可以,支持斜线的墙
+				//console.log('N.z==0 && N.x == 0?');  
+				var c = ( N.x*(A.x-O.x) + N.y*(A.y-O.y) + N.z*(A.z-O.z));
+				if(c == 0){console.log("分母为0?? return;");return;} 
+				var t = -((N.x*O.x + N.y*O.y + N.z*O.z) - (P.x*N.x + P.y*N.y + P.z*N.z) ) / c
+				var x = t * (A.x - O.x) + O.x;
+				var y = t * (A.y - O.y) + O.y;
+				var z = t * (A.z - O.z) + O.z;
+				/*原理: 已知空间直线L:(x-a)/m=(x-b)/n=(z-c)/p和空间平面π:Ax+By+Cz+D=0;
+				求直线L与平面π的交点的坐标。
+				把直线方程改写成参数形式:设(x-a)/m=(x-b)/n=(z-c)/p=t;
+				则x=mt+a;y=nt+b;z=pt+c;代入平面π的方程得:
+				A(mt+a)+B(nt+b)+C(pt+c)+D=0
+				由此解得t=-(Aa+Bb+Cc+D)/(Am+Bn+Cp)
+				再代入参数方程即得交点的坐标(x,y,z). */
+			}else if(N.x ==0 ){ //z与pullPos相等
+				var z = P.z;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.z == z){console.log('一样3??');return;}
+				var r = (O.z-z)/(A.z-z);
+				var x = (r*A.x-O.x)/(r-1);
+				var y = (r*A.y-O.y)/(r-1);
+			}else if(N.z == 0){//x与pullPos相等
+				var x = P.x;
+				if(O.y == A.y){console.log('一样??');return;}
+				if(A.y == y){console.log('一样2??');return;}
+                if(A.x == x){console.log('一样3??');return;}
+				var r = (O.x-x)/(A.x-x);
+				var y = (r*A.y-O.y)/(r-1);
+				var z = (r*A.z-O.z)/(r-1);
+			}
+		}   
+		
+		return new THREE.Vector3(x,y,z);
+	},
+
+
+	
+	getMouseIntersect : function(camera, meshes, mouse){//获取鼠标和meshes交点
+		var raycaster = new THREE.Raycaster; 
+		camera.updateMatrixWorld(); 
+		var origin = new THREE.Vector3(mouse.x,mouse.y,-1).unproject(camera)
+		  , end = new THREE.Vector3(mouse.x,mouse.y,1).unproject(camera); 
+		var dir = end.sub(origin).normalize() 
+		raycaster.set(origin, dir);
+		var n = raycaster.intersectObjects(meshes);
+		if (0 === n.length)
+			return null;
+		return n[0];
+		
+	},
+	ifIntersectChunks : function(A,B,options={}){//获取某个线段/射线和meshes的交点 
+		var dir = B.clone().sub(A).normalize();
+		var len = options.InfinityLen ? Infinity :  A.distanceTo(B) + (options.extLen||0);
+		var ray = new THREE.Raycaster(A.clone(), dir, 0, len);
+          
+		var o = ray.intersectObjects(options.model || player.model.colliders);
+		if (o && o.length)return o;
+		  
+		if(options.throughWidth){ //允许最小宽度,防止穿过极小的缝隙导致撞墙感
+			var normal = math.getNormal({points:[{x:A.x, y:A.z},{x:B.x, y:B.z}]});//线段法线
+			normal.multiplyScalar(options.throughWidth)
+			var normalVec3 = new THREE.Vector3(normal.x, 0, normal.y);
+			
+			var A2 = A.clone().add(normalVec3)
+			ray.set(A2, dir);  
+			var o2 = ray.intersectObjects(options.model || player.model.colliders);
+			ray.set(A.clone().add(normalVec3.negate()), dir);
+			if (o2 && o2.length)return o2;
+			var o3 = ray.intersectObjects(options.model || player.model.colliders);
+			if (o3 && o3.length)return o3; 
+		} 
+		return null;
+	},
+	getPosAtSphere : function(pos3d, toPanoPos){
+		var dir = pos3d.clone().sub(toPanoPos); 
+		dir.normalize();//然后计算在球中
+		dir.multiplyScalar(Constants.skyRadius);   
+		dir.add(toPanoPos); 
+		return dir;
+	},
+	getVisiblePano: function(position,options){//获取某个坐标的可见pano。即没有遮挡的位置。
+        options = options || {}
+		var visiblePanos = [];
+		var wallDepth = 0.075, discScale = 0.06;
+		var B = position.clone(); 
+		var panos = player.model.panos.index;
+		 
+		for (var i in panos) { 
+            if(!panos[i].isAligned())continue;
+			var A = panos[i].position.clone();
+			  
+			var ray = new THREE.Raycaster(A.clone(), B.clone().sub(A).normalize(), 0, A.distanceTo(B) - discScale / 2 - wallDepth);
+			var o = ray.intersectObjects(options.model || player.model.colliders,true);
+			 
+			/* if(this.snapInfo){ 
+				ray.set(A, C.clone().sub(A).normalize());
+				ray.far = A.distanceTo(C) - this.discScale / 2 - wallDepth
+				var o2 = ray.intersectObjects(this.model.colliders);
+				if (!o || !o.length || !o2 || !o2.length) { 
+					this.visiblePanos.push(panos[i].id);
+				}
+				//是否要将o2的删除 如果热点准确些不会到房子外面的话。   或者如果o的可见没有时采用2
+				 
+			}else{ */
+				if (!o || !o.length)visiblePanos.push(panos[i].id);
+			//}   
+		}
+		return visiblePanos
+	}
+
+}
+
+   
 
 g_playAudio = null
 
@@ -4620,30 +4811,49 @@ function o(a, s, l) {
             ,
             t.prototype.goToDestination = function(e, t, i, n) { 
                 //音频
-                if(this.destinationItem[1] == 0){//如果是每个folder的起始
-                    var musicInfo = this.model.heroLocations[this.destinationItem[0]].musicInfo
-                    if(musicInfo && musicInfo.music){
-                        var o = musicInfo.music.includes(g_Prefix.slice(-10)) ? musicInfo.music :  g_Prefix + musicInfo.music;
-                        g_tourAudio.src = manage.dealURL(o);
+                                                                                 
+                var musicInfo = this.model.heroLocations[this.destinationItem[0]].musicInfo
+                if(musicInfo && musicInfo.music){
+                    var o1 = musicInfo.music.includes(g_Prefix.slice(-10)) ? musicInfo.music :  g_Prefix + musicInfo.music;
+                    
+                    let audioSrc1 = g_tourAudio.src.split('/').pop();
+                    let audioSrc2 = o1.split('/').pop();
+               
+                    if(audioSrc1 == audioSrc2){//应该是继续播放该folder 
+                        if(this.destinationItem[1] == 0){//从头开始播放 因为可能暂停后然后再点该缩略图播
+                            g_tourAudio.currentTime = 0;  g_tourAudio.play();
+                        }else if(g_tourAudio.paused && g_tourAudio.currentTime < g_tourAudio.duration){//未播完
+                            g_tourAudio.play()
+                        } 
+                        
+                    }else{//很可能是该folder的起始
+                        g_tourAudio.src = manage.dealURL(o1);
                         g_tourAudio.load()  
                     }
+                    
                 }
                 
                 
                 if (this.onTheBus = !0,
                 this.emit("update.controls"),
                 this.player.updateLastView(),
-                n || !this.atDestinationPano())
+                n || !this.atDestinationPano()){
                     if (this.player.flying || this.player.isWarping())
                         m.warn("Cannot go to new destination while player is flying or warping.");
                     else {
                         var a = this.model.getHeroDescriptorByIndex(this.destinationItem)
                           , s = null
                           , l = null;
-                        if (a.isPano()) {
-                            o = this.getMomentTour(this.destinationItem)   //window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
-                            l = this.player.warpToPanoByHeroIndex.bind(this.player, this.destinationItem, g.Show, f.Slow, o, !0, i, this.actionComplete.bind(this)),
+                        if (a.isPano()) {  
+                            o1 = this.getMomentTour(this.destinationItem)   //window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
+                            l = this.player.warpToPanoByHeroIndex.bind(this.player, this.destinationItem, g.Show, f.Slow, o1, !0, i, this.actionComplete.bind(this)),
                             s = this.arrivedAtDestination.bind(this, !0)
+                             
+                            //add
+                            if(a.zoom && a.zoom != this.player.zoomLevel){
+                                this.player.smoothZoomFovTo(null, a.zoom,  r.warp.teleportTime) //瞬间过渡的时间
+                            }
+                            
                         } else{
                             l = this.player.warpToNonPanoByHeroIndex.bind(this.player, this.destinationItem, this.actionComplete.bind(this)),
                             s = this.arrivedAtDestination.bind(this, !1);
@@ -4656,8 +4866,15 @@ function o(a, s, l) {
                         .bind(this), s),
                         this.emit("update.controls")
                     }
-                else
+                }else{
+                    //add
+                    var a = this.model.getHeroDescriptorByIndex(this.destinationItem)
+                    if(a.zoom && a.zoom != this.player.zoomLevel){
+                        this.player.smoothZoomFovTo(null, a.zoom,  r.warp.teleportTime) //瞬间过渡的时间
+                    }
+                    
                     this.arrivedAtDestination(!0)
+                }
             }
             ,
             t.prototype.tourInterlude = function() {
@@ -4919,7 +5136,7 @@ function o(a, s, l) {
                 } */
                  
                 
-                var momentTour = this.getMomentTour(this.destinationItem);
+                /* var momentTour = this.getMomentTour(this.destinationItem);
                 if ( "black" === momentTour) { // 方奕卓 瞬间过渡, 相机缩放至1 
                     var i = this.player.zoomLevel;
                     this.player.zoomEnabled = !0;
@@ -4928,23 +5145,26 @@ function o(a, s, l) {
                     }
                     .bind(this);
                     o.start(t, 1500, function() {}, 0, h.easeOutQuad, "zoom")
-                }
+                } */
                 this.goToDestination()
             }
             ,
-            t.prototype.getMomentTour = function(destinationItem) {//add
-                /* if(!item) return window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
-                var currentLocation = this.model.heroLocations[item[0]];
-                var currentChildNum = currentLocation.heroLocations ? currentLocation.heroLocations.length : 1
-                if(item[1]>=currentChildNum-1){//子目录中最后一个
-                    return window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
-                }else{
-                    return currentLocation.momentTour || "walk";
-                } */
-                if(!destinationItem || destinationItem[1] == 0) return window.MP_PREFETCHED_MODELDATA.momentTour || "walk";
+            t.prototype.getMomentTour = function(destinationItem) {//add 
+                                                                                        
+                                                                        
+                                                                                                              
+                                                                         
+                var wholeMomentTour = window.MP_PREFETCHED_MODELDATA.momentTour || "walk"; //最外层
+                
+                                                                
+                    
+                if(!destinationItem) return wholeMomentTour
                 else{
-                    var currentLocation = this.model.heroLocations[destinationItem[0]];
-                    return currentLocation.momentTour || "walk";
+                    var currentLocation = this.model.getHeroDescriptorByIndex(destinationItem)//最内层。 如果有使用最内层
+                    if(currentLocation.momentTour)return currentLocation.momentTour;
+                    
+                    var currentLocation_ = this.model.heroLocations[destinationItem[0]];
+                    return  currentLocation_.heroLocations ? currentLocation_.momentTour : wholeMomentTour; //如果有中间层,使用中间层,否则使用最外层
                 }
             }
             ,
@@ -16753,6 +16973,7 @@ function o(a, s, l) {
                             sid: n.sid 
                         }
                         var item = new p(l);
+                        item.momentTour = n.momentTour
                         container.push(item) 
                         return item
                     }
@@ -18518,9 +18739,9 @@ function o(a, s, l) {
                 this.removeTextSprite();
                 var i = document.createElement("canvas")
                   , n = i.getContext("2d");
-                i.width = 256,
-                i.height = 256;
-                n.font = "bold 60px Arial",
+                i.width = 1024,
+                i.height = i.width / ratio;
+                n.font = " 30px Arial",
                 n.fillStyle = "white";
                 var r = n.measureText(e).width;
                 n.fillText(e, (i.width - r) / 2, (i.height + 60) / 2);
@@ -18533,6 +18754,9 @@ function o(a, s, l) {
                 this.text3d = new s.Sprite(a),
                 this.text3d.position.copy(this.skyboxMesh.position),
                 this.floor.add(this.text3d)
+                var scale = 3
+                this.text3d.scale.y = scale/ratio
+                this.text3d.scale.x = scale
             }
             ,
             r.prototype.removeTextSprite = function() {
@@ -19102,7 +19326,7 @@ function o(a, s, l) {
             ,
             t.prototype.getHeroDescriptorByHeroIndex = function(e) {
                 var t = this.model.heroCount();
-                if (null !== this.warpDestHeroLoc && t < 2)
+                if (null !== this.warpDestHeroLoc && t < 1)
                     return H.info("ShowPath.getHeroDescriptorByHeroIndex() -> Only one hero location is available."),
                     this.model.getHeroDescriptorByIndex(0);
                 var i = this.model.getHeroDescriptorByIndex(e);
@@ -19597,6 +19821,7 @@ function o(a, s, l) {
                             var n = this.playerControls.cameras[O.PANORAMA];
                             a.setFromQuaternion(n.quaternion, D.warp.eOrder);
                             var r = i * l / o;
+                            r = Math.sign(r) * Math.max(r, 0.0001) //add  如果音频长的话,使旋转可见,否则以为停住了
                             a.y += r,
                             s.set(0, 0, -1),
                             s.applyEuler(a),
@@ -21744,38 +21969,54 @@ function o(a, s, l) {
                     }
                     hots[index].mesh.visible = visible; 
                 } 
-            },
+            } 
                 
-            
+            var getQuaByAim = function (aim, center) {
+                return new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 0, -1), aim.clone().sub(center).normalize())
+                //或var _ = (new THREE.Matrix4).lookAt(pano.position, aim, new THREE.Vector3(0,1,0));  aimQua = (new THREE.Quaternion).setFromRotationMatrix(_);
+            } 
+
             t.prototype.flyToPano = function(e, t) {
                 
-                //e.duration = 100
-                
-                var i, n = e.pano, r = e.lookAtPoint, o = e.duration, a = e.aimDuration, s = e.maxDistanceOverride, l = e.skipWarpingCheck, c = e.constantMoveSpeed, h = null, u = null;
+                var i, n = e.pano, aim = e.lookAtPoint, aimQua = e.quaternion,//ADD
+                o = e.duration, a = e.aimDuration, s = e.maxDistanceOverride, 
+                l = e.skipWarpingCheck, c = e.constantMoveSpeed, h = null, u = null 
+                if (aim) aimQua = getQuaByAim(aim, n.position)
+                else aimQua = aimQua 
+            
+                var zoomLevel = e.zoomLevel || 1  //add
+                 
                  
+                if(this.flying) return t && t(e)
                 if (window.specialScene && specialScene.special().specifySpot && specialScene.special().specifySpot(n),
                 this.isWarping() && !l && (this.path.activeTransType === R.BLACK || this.path.activeTransType === R.STD))
                     return Y.warn("Player.flyToPano() -> Cannot fly when warping"),
                     t && t(),
                     !1;
-                if (this.updateLastView(),
-                this.mode !== V.PANORAMA)
-                    return r && (i = (new B.Quaternion).setFromUnitVectors(T.FORWARD, r.sub(n.position).normalize())),
+                    
+                this.updateLastView()
+                if (this.mode !== V.PANORAMA) 
+                                                                                                                      
                     void this.flyToNewMode({
                         mode: V.PANORAMA,
                         pano: n,
                         duration: o,
-                        quaternion: i,
+                        quaternion: aimQua,
                         callback: t
                     });
-                if (!n || (h = x.deepExtend(e),
-                u = function() {
+                    
+                    
+                    
+                    
+                if (!n || (h = x.deepExtend(e), u = function() {
                     j.delayOneFrame(function() {
                         this.flyToPano(h, t)
-                    }
-                    .bind(this))
-                }
-                .bind(this),
+                     
+                    }.bind(this))
+                 
+                }.bind(this),
+                
+                
                 !this.checkAndWaitForPanoLoad(n, "high", "low", this.basePanoSize, u))) {
                     var d = function(e) {
                         t && t(e)
@@ -21790,40 +22031,44 @@ function o(a, s, l) {
                         var f = s || k.transition.flytimeMaxDistanceThreshold;
                         p = Math.min(this.currentPano.position.distanceTo(n.position), f) * k.transition.flytimeDistanceMultiplier + k.transition.flyTime
                     }
+                    
+                    
                     if (.01 < k.transition.flySpeed && (p = 1e3 * this.currentPano.position.distanceTo(n.position) / k.transition.flySpeed),
-                    1 !== this.zoomLevel)
+                    zoomLevel !== this.zoomLevel)
                         switch (k.zoom.transitionStyle) {
                         case 1:
-                            this.smoothZoomToDefault(p / 2);
+                            this.smoothZoomFovTo(null, zoomLevel, zoomLevel == 1 ? p / 2 : p); //改
                             break;
                         case 2:
                             return h = x.deepExtend(e),
                             u = this.flyToPano.bind(this, h, t),
-                            void this.smoothZoomToDefault(k.zoom.restoreTime * (this.zoomLevel - 1), u)
+                            void this.smoothZoomFovTo(null, zoomLevel, k.zoom.restoreTime * (this.zoomLevel - 1), u)
                         }
-                    if (r) {
+                        
+                        
+                    if (aimQua) {
                         G.cancelById(q.LookTransition),
                         p *= k.transition.aimSlowFactor;
-                        var g = this.cameraControls.activeControl.camera.quaternion.clone()
-                          , m = (new B.Matrix4).lookAt(n.position, r, T.UP)
-                          , v = (new B.Quaternion).setFromRotationMatrix(m)
+                        var g = this.cameraControls.activeControl.camera.quaternion.clone() 
+                                                                           
+                                                                           
                           , y = g.clone()
                           , A = new B.Vector3;
                         if (n === this.currentPano) {
                             var C = T.FORWARD.clone().applyQuaternion(g)
-                              , I = T.FORWARD.clone().applyQuaternion(v)
+                              , I = T.FORWARD.clone().applyQuaternion(aimQua)
                               , E = C.angleTo(I);
                             return null != a || (a = 1 * Math.sqrt(E) / k.tags.navigate.rotateSpeedFactor * 1e3),
                             void G.start(function(e) {
                                 y.copy(g),
-                                H.quaternion(y, v)(e),
+                                H.quaternion(y, aimQua)(e),
                                 A.copy(T.FORWARD).applyQuaternion(y).add(this.cameraControls.activeControl.camera.position),
                                 this.cameraControls.activeControl.lookAt(A)
                             }
                             .bind(this), a, d, 0, z[k.transition.movementEasing], null, q.LookTransition)
                         }
                     }
-                    if (n === this.currentPano || this.flying)
+                    if (n === this.currentPano  )
                         return void d();
                     this.flying = !0;
                     var _ = this.position.clone()
@@ -21840,9 +22085,9 @@ function o(a, s, l) {
                     
                     
                     
-                    r && G.start(function(e) {
+                    aimQua && G.start(function(e) {
                         y.copy(g),
-                        H.quaternion(y, v)(e),
+                        H.quaternion(y, aimQua)(e),
                         A.copy(T.FORWARD).applyQuaternion(y).add(this.cameraControls.activeControl.camera.position),
                         this.cameraControls.activeControl.lookAt(A)
                     }
@@ -21878,9 +22123,6 @@ function o(a, s, l) {
             }
             ,
             
-            
-            
-            
             window._transitionPosId = 9999
             
             t.prototype.transitionPos = function(o={}) {//渐变overlay和热点的位置
@@ -22245,7 +22487,7 @@ function o(a, s, l) {
                     this.transitionPos({type:"beforeFlyOut",  dur:p/2})//add                       
                 }
                 if(this.mode == 'panorama'){
-                    this.overlayGroup.visible = false;
+                    //this.overlayGroup.visible = false;
                     this.overlayGroup.children.forEach((overlay)=>{
                         overlay.overlayType == "video"  &&  overlay.plane.material.map.image.pause()
                     })
@@ -22349,7 +22591,7 @@ function o(a, s, l) {
                         this.overlayGroup.visible = true;
                         Overlay.updateVisibles([this.currentPano])
                     }else{
-                        //Overlay.updateVisibles(true) 
+                        Overlay.updateVisibles(true) 
                     }
                     
                     c && u !== V.PANORAMA && i === V.PANORAMA ? this.startWarp(M.Retain, S.Retain, R.BLACK, null, null, a) : (a && a(),
@@ -22522,20 +22764,20 @@ function o(a, s, l) {
                 var currentLocation = this.model.heroLocations[this.director.currentItem[0]] 
                 var restChildCount = currentLocation.heroLocations ? (currentLocation.heroLocations.length-this.director.currentItem[1]-1) : 0
                 var current = g_tourAudio ? 1e3 * g_tourAudio.currentTime : 0
-                var waitTime = currentLocation && currentLocation.musicInfo.music ? currentLocation.musicInfo.time - current : 2e3;  
+                var rotTime = currentLocation && currentLocation.musicInfo.music ? currentLocation.musicInfo.time - current : 2e3;  
                 
                 if(restChildCount){//如果当前folder中还有剩下的item,平分一下时间
                     var timeEachItem = 2000;//假设每个item飞的时间
-                    var waitTime = Math.max(0, (waitTime-timeEachItem*restChildCount) / (restChildCount+1));
+                    var rotTime = (rotTime-timeEachItem*restChildCount) / (restChildCount+1);
                      
                 } 
-                
-                console.log("waitTime "+waitTime +" at item "+this.director.currentItem + ",musicCurrentTime:"+current) 
+                rotTime = Math.max(0, rotTime)
+                console.log("rotTime "+rotTime +" at item "+this.director.currentItem + ",musicCurrentTime:"+current) 
                  
                 this.path.waitNextStep(e, function() {//等待音乐播放一段时间再下一步,此时镜头会缓慢旋转
                     t && t()
                 }
-                .bind(this), waitTime)
+                .bind(this), rotTime)
             }
             ,
             t.prototype.stopInterlude = function() {
@@ -22660,6 +22902,22 @@ function o(a, s, l) {
                 G.start(r, e, o, null, 0, z[k.transition.blendEasing])
             }
             ,
+            t.prototype.smoothZoomFovTo = function (fov, zoomLevel, dur, callback) {//add
+                
+                var i,
+                    n = this.zoomLevel,
+                    aimLevel = zoomLevel || this.baseFov / fov
+
+                if (n == aimLevel) return
+
+                var fun = function (e) {
+                    e > 1 && (e = 1), (i = n * (1 - e) + e * aimLevel), this.zoomTo(i, !0)
+                }.bind(this)
+
+                G.start(fun, dur, callback, null, 0, z[k.transition.easeInCubic])
+            }
+            
+            
             t.prototype.updateZoomPano = function() {
                 if (!this.panoRenderer.zoomPanoRenderingDisabled && this.mode === V.PANORAMA) {
                     var e = this.currentPano;
@@ -23331,7 +23589,7 @@ function o(a, s, l) {
                         e.visible = !1
                     })),
                     i.cursor.visible = e,
-                    i.setSize(window.innerWidth, window.innerHeight),
+                    i.setSize($("#player").width(), $("#player").height()),
                     window._vrEnabled = e,
                     setTimeout(function() {
                         console.log(player.cameraControls.activeControl.camera.fov)
@@ -29014,11 +29272,33 @@ function o(a, s, l) {
             extend: function(e, t) {
                 for (var i in t.prototype)
                     e.prototype[i] = t.prototype[i]
+            },  
+            getVisiblePano : function(position, options={}){//add
+                var visiblePanos = []; 
+                var B = position.clone(); 
+                var panos = options.panos ||  player.model.panos.list;
+                 
+                panos.forEach((pano)=>{
+                    if(!pano.isAligned())return;
+                    var A = pano.position.clone();
+                      
+                    var ray = new THREE.Raycaster(A.clone(), B.clone().sub(A).normalize(), 0, A.distanceTo(B) - (options.tolerance||0) ) 
+                    var o = ray.intersectObjects(options.model || player.model.colliders, true);
+                     
+                     
+                    if (!o || !o.length)visiblePanos.push(pano );
+                     
+                    
+                })  	  
+             
+                return visiblePanos
+             
             }
         },
         Math.sign = function(e) {
             return e < 0 ? -1 : 1
         }
+        window.common = t.exports
     }
     , {
         three: 217
@@ -29456,6 +29736,7 @@ function o(a, s, l) {
                 };
             },
         }
+        window.math = t.exports                          
     }
     , {
         "../constants": 8,