|
@@ -2,6 +2,19 @@
|
|
|
//合并热点和展览
|
|
|
g_currentHot = null
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+const playVideoWhenFlyOut = false
|
|
|
+//同时可播放的最大个数:
|
|
|
+const playVideoMax = window.isEdit ? 4 : browser.isMobile() ? 2 : 3;
|
|
|
+const playAniMax = window.isEdit ? 8 : browser.isMobile() ? 3 : 6;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
window.initHot = function(model){
|
|
|
|
|
|
var objLoader = new THREE.OBJLoader()
|
|
@@ -16,6 +29,9 @@ window.initHot = function(model){
|
|
|
|
|
|
var defaultTex1 = Texture.load(g_HotImage.point);
|
|
|
var defaultTex2 = Texture.load(g_HotImage.point2)
|
|
|
+ dealMap(defaultTex1,{ignoreResize:true} );
|
|
|
+ dealMap(defaultTex2,{ignoreResize:true} ); //这张图改为linear有黑边。 但即使不改,chrome调试手机版也有黑边和锯齿
|
|
|
+
|
|
|
|
|
|
/* var _boxMat = new THREE.MeshBasicMaterial({
|
|
|
color: "#eeeeee",
|
|
@@ -28,7 +44,11 @@ window.initHot = function(model){
|
|
|
opacity: 0.8,
|
|
|
side:THREE.DoubleSide
|
|
|
})
|
|
|
- var autoSizeInfo = {minSize : 120, maxSize : 600, nearBound : 1 , farBound : 15}
|
|
|
+
|
|
|
+ var autoSizeInfo = /* {width2d:50}// */{minSize : 120, maxSize : 600, nearBound : 1 , farBound : 15}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
var hotGroup = new THREE.Object3D; hotGroup.name = "hotGroup"
|
|
|
model.add(hotGroup); model.hotGroup = hotGroup
|
|
@@ -71,11 +91,7 @@ window.initHot = function(model){
|
|
|
if(mat) return mat
|
|
|
else{
|
|
|
var mat = new THREE.ShaderMaterial({
|
|
|
- uniforms: {
|
|
|
- color: {
|
|
|
- type: "c",
|
|
|
- value: new THREE.Color(16720384)
|
|
|
- },
|
|
|
+ uniforms: {
|
|
|
opac: {
|
|
|
type: "f",
|
|
|
value: 0
|
|
@@ -90,7 +106,7 @@ window.initHot = function(model){
|
|
|
}
|
|
|
},
|
|
|
vertexShader: "varying vec2 vUv;\n\nvoid main() {\n\n vUv = uv ;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}\n",
|
|
|
- fragmentShader: "varying vec3 vNormal;\n\nvarying vec2 vUv;\n\nuniform float opac;\n\nuniform vec3 color;\n\nuniform sampler2D texture1;\n\nuniform sampler2D texture2;\n\nvoid main() {\n\nvec4 tcolor1 = texture2D( texture1, vUv );\n\nvec4 tcolor2 = texture2D( texture2, vUv );\n\ngl_FragColor = mix(tcolor1,tcolor2 ,opac) + tcolor2*0.2; }\n"
|
|
|
+ fragmentShader: "varying vec3 vNormal;\n\nvarying vec2 vUv;\n\nuniform float opac;\n\n uniform sampler2D texture1;\n\nuniform sampler2D texture2;\n\nvoid main() {\n\nvec4 tcolor1 = texture2D( texture1, vUv );\n\nvec4 tcolor2 = texture2D( texture2, vUv );\n\ngl_FragColor = mix(tcolor1,tcolor2 ,opac) + tcolor2*0.2; }\n"
|
|
|
,transparent: !0
|
|
|
})
|
|
|
shineMats.push(mat)
|
|
@@ -130,7 +146,7 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
this.sid = info.sid;
|
|
|
- this.preDeal(info, source)// source:来源
|
|
|
+ this.preDeal(info, source)// source:旧版来源
|
|
|
|
|
|
this.info = info
|
|
|
this.cornerPoints = []
|
|
@@ -145,28 +161,7 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
|
|
|
- build(info) {
|
|
|
- /* this.changeMaterial(new THREE.MeshBasicMaterial({
|
|
|
- color: "#00c8af",
|
|
|
- opacity: 0.4,
|
|
|
- transparent: !0,
|
|
|
- polygonOffset: true,
|
|
|
- //是否开启多边形偏移 //ie不开启时blank也不会闪烁
|
|
|
- polygonOffsetFactor: -0.9,
|
|
|
- //多边形偏移因子
|
|
|
- polygonOffsetUnits: -4.0,
|
|
|
- //多边形偏移单位
|
|
|
- }))
|
|
|
-
|
|
|
- if(!info.objSrc){
|
|
|
- this.addPlane()
|
|
|
- if (info.hasBox) this.addBox(true)
|
|
|
- }else{
|
|
|
- this.addModel(new THREE.Mesh())//暂时创建个空的
|
|
|
-
|
|
|
- } */
|
|
|
-
|
|
|
-
|
|
|
+ build(info) {
|
|
|
hotGroup.add(this)
|
|
|
this.setTitleElem()
|
|
|
this.setFromInfo(info)
|
|
@@ -330,13 +325,12 @@ window.initHot = function(model){
|
|
|
video = media
|
|
|
}else{
|
|
|
if(!this.info.texSrc)return
|
|
|
- var video = $(`<video controls="controls" loop autoplay x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload"></video>`)[0]
|
|
|
- video.src = manage.dealURL(this.info.texSrc);
|
|
|
+ var video = $(`<video controls="controls" loop autoplay x5-playsinline="" webkit-playsinline="true" playsinline="true" controlslist="nodownload" preload="meta" ></video>`)[0]
|
|
|
+ if(window.isEdit) video.src = manage.dealURL(this.info.texSrc); //注意,src赋值就会自动加载, preload="meta" 只加载元数据,提高加载速度,否则一开始卡
|
|
|
video.name = this.info.fileName
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
video.setAttribute("crossOrigin", 'Anonymous')//要在src设置好前解决跨域
|
|
|
|
|
|
$(video).on('contextmenu', function() {
|
|
@@ -346,18 +340,23 @@ window.initHot = function(model){
|
|
|
|
|
|
this.texMedia = video;
|
|
|
|
|
|
- video.oncanplaythrough = ()=> {
|
|
|
- if(this.texMedia == video){
|
|
|
- this.material_.map.needsUpdate = !0
|
|
|
- video.play()
|
|
|
+ video.oncanplaythrough = (e)=> {
|
|
|
+ if(this.texMedia == video){
|
|
|
+ //console.log('oncanplaythrough',e,this.sid)
|
|
|
+ //this.material_.map.needsUpdate = !0 //当初为何加这句?
|
|
|
+ //this.update(player)
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
|
|
|
video.volume = 0
|
|
|
video.muted = true
|
|
|
video.currentTime = 0
|
|
|
|
|
|
+
|
|
|
+ if(!window.isEdit) this.material_.opacity = 0.1;
|
|
|
this.material_.map = new THREE.VideoTexture(video)
|
|
|
this.material_.map.wrapS = this.material_.map.wrapT = THREE.ClampToEdgeWrapping;
|
|
|
|
|
@@ -371,7 +370,7 @@ window.initHot = function(model){
|
|
|
this.material_.map = new THREE.Texture(); //texture也不能共用一个,因为有的会有动画,就不一样
|
|
|
this.material_.map.image = media //image可以共用
|
|
|
this.material_.map.needsUpdate = !0
|
|
|
-
|
|
|
+ this.material_.opacity = 1
|
|
|
}else{
|
|
|
if(!this.info.texSrc)return
|
|
|
this._loadDones = []
|
|
@@ -395,8 +394,8 @@ window.initHot = function(model){
|
|
|
/* this.material_.map.minFilter = THREE.LinearFilter;
|
|
|
this.material_.map.magFilter = THREE.LinearFilter; */
|
|
|
dealMap(this.material_.map);
|
|
|
- this.material_.color.set("#FFFFFF");
|
|
|
- this.material_.opacity = 1
|
|
|
+ this.material_.color.set("#FFFFFF");
|
|
|
+
|
|
|
this.material_.needsUpdate = true
|
|
|
}
|
|
|
|
|
@@ -414,7 +413,8 @@ window.initHot = function(model){
|
|
|
if(styleImg.length){
|
|
|
tex1 = Texture.load(styleImg[0].src);
|
|
|
tex2 = Texture.load(styleImg[1]&&styleImg[1].src || styleImg[0].src);
|
|
|
-
|
|
|
+ dealMap(tex1,{ignoreResize:true} )
|
|
|
+ dealMap(tex2,{ignoreResize:true} )
|
|
|
}else{
|
|
|
tex1 = defaultTex1;
|
|
|
tex2 = defaultTex2;
|
|
@@ -442,40 +442,7 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /*
|
|
|
- actionType: "common"
|
|
|
- infoAttribute: {images: [], styleImg: [], model: [], video: [], bgName: "background", iframe: [], title: "11",…}
|
|
|
- bgName: "background"
|
|
|
- content: "111"
|
|
|
- iframe: []
|
|
|
- images: []
|
|
|
- model: []
|
|
|
- styleImg: []
|
|
|
- title: "11"
|
|
|
- video: []
|
|
|
- isSprite: 0
|
|
|
- link: "https://www.4dmodel.com/SuperTwo/hot_online1/index.html#/?m=EDwn769489868"
|
|
|
- linkType: "common"
|
|
|
- noAction: 0
|
|
|
- order: 4
|
|
|
- position: {x: -4.238, y: 1.32, z: -0.648}
|
|
|
- rotation: {x: 0, y: 0.018105110200249575, z: 0}
|
|
|
- transformAtPanos: {}
|
|
|
- IO4Kq7494332: {actionTy
|
|
|
-
|
|
|
-
|
|
|
- depth: 0.08
|
|
|
- file: "https://super.4dage.com/data/TEST/edit/20200805_172635119.mp4"
|
|
|
- hasBox: 1
|
|
|
- height: 0.7289
|
|
|
- media: ["video"]
|
|
|
- pos: [-5.562, 1.349, 1.994]
|
|
|
- qua: [0, 0.70672, 0, 0.70749]
|
|
|
- sid: "1596619585929"
|
|
|
- transformAtPanos: {,…} */
|
|
|
+
|
|
|
|
|
|
preDeal(info, source){// source:来源
|
|
|
|
|
@@ -532,7 +499,7 @@ window.initHot = function(model){
|
|
|
info.rotation = new THREE.Euler().setFromVector3(convertValue(info.rotation, THREE.Vector3 )) //热点的旧数据很多是字符串
|
|
|
}
|
|
|
|
|
|
- var s = Hot.getDefaulScale(info.hotIconScale)
|
|
|
+ var s = Hot.getDefaulScale(info.hotIconScale) //旧版的大小,统一转换成新版
|
|
|
info.scale = new THREE.Vector3(s,s,0.02)
|
|
|
|
|
|
|
|
@@ -583,6 +550,12 @@ window.initHot = function(model){
|
|
|
info.video = info.video || []
|
|
|
info.iframe = info.iframe || []
|
|
|
info.styleImg = info.styleImg || []
|
|
|
+ info.imagesDesc = info.imagesDesc || []
|
|
|
+ info.videosDesc = info.videosDesc || []
|
|
|
+ info.titleShowType = info.titleShowType || 'hover'
|
|
|
+ info.titlePos = info.titlePos || 'right'
|
|
|
+
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
@@ -741,7 +714,7 @@ window.initHot = function(model){
|
|
|
}));
|
|
|
|
|
|
if(end>=model.panos.list.length){
|
|
|
- console.log(window.hotsi ?(++window.hotsi): (window.hotsi = 1))
|
|
|
+ //console.log(window.hotsi ?(++window.hotsi): (window.hotsi = 1))
|
|
|
clearInterval(interval)
|
|
|
}
|
|
|
}, Hot.visiEveryDurSlice )// visiEveryDurSlice 等在main中定义
|
|
@@ -756,6 +729,7 @@ window.initHot = function(model){
|
|
|
}
|
|
|
|
|
|
this.visible = visibility != void 0 ? visibility : (!this.info.visiblePanos || !!panos.find(pano=>this.info.visiblePanos.includes(pano.id)))
|
|
|
+ this.titleElem && this.titleElem.setVisible(this.visible, 'hotVisible')
|
|
|
|
|
|
if (this.texType == 'video'){
|
|
|
//this.switchPlay(this.visible, this.visible ? null : 'stop' );//可见时不操作;不可见时停止
|
|
@@ -868,26 +842,61 @@ window.initHot = function(model){
|
|
|
|
|
|
return this.cornerPoints[player.currentPano.id]
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+ getMediaSize(){
|
|
|
+ let size = new THREE.Vector2;
|
|
|
+ if(this.texMedia){
|
|
|
+ if(this.texType == 'photo'){
|
|
|
+ size.x = this.texMedia.width;
|
|
|
+ size.y = this.texMedia.height;
|
|
|
+ //动画的话再变
|
|
|
+ if(this.info.animateInfo){
|
|
|
+ size.x /= this.info.animateInfo.cellXcount
|
|
|
+ size.y /= this.info.animateInfo.cellYcount
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ size.x = this.texMedia.videoWidth || this.videoWidth
|
|
|
+ size.y = this.texMedia.videoHeight || this.videoHeight
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return size
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
inSight(){
|
|
|
//return true
|
|
|
if(window.isEdit)return true // 太容易move了
|
|
|
|
|
|
- if(player.mode == 'panorama'){
|
|
|
+ if(player.mode == 'panorama' && player.currentPano){
|
|
|
if(!player.camera) return
|
|
|
|
|
|
var cornerPointInfo = this.getCornerPoint();
|
|
|
var cornerPoint
|
|
|
+
|
|
|
+
|
|
|
+ let min = new THREE.Vector2(5,5)
|
|
|
+ let scaleRatio = 1/player.zoomLevel;
|
|
|
+
|
|
|
+ //根据media原始大小来调整阈值: media的原始大小能代表期望显示的大小,如果显示大小的远小于期望大小,就不显示(此时能感受到贴图锯齿严重,清晰度被浪费)。比如如果gif是一个很小的按钮,即使diffLon很小也要显示。缺点:需要用户根据所需上传合适清晰度的图。
|
|
|
+
|
|
|
+ let size = this.getMediaSize()
|
|
|
+ if(size.x>0){
|
|
|
+ scaleRatio *= Math.sqrt(size.x * size.y) / 1000
|
|
|
+ }
|
|
|
+ min.multiplyScalar(scaleRatio)
|
|
|
+
|
|
|
+
|
|
|
+ if(cornerPointInfo.diffLon < min.x || cornerPointInfo.diffLat < min.y ){
|
|
|
+ //console.log('two far and small')
|
|
|
+ return false
|
|
|
+ }
|
|
|
+
|
|
|
if(cornerPointInfo.diffLon < 15 && cornerPointInfo.diffLat < 15){//当很小的时候,只判断中心点即可
|
|
|
cornerPoint = [cornerPointInfo.cornerPoint[0]];
|
|
|
}else{
|
|
@@ -902,39 +911,24 @@ window.initHot = function(model){
|
|
|
}
|
|
|
|
|
|
}else{//飞出要判断模型阻挡,有点耗时就算了
|
|
|
- return true
|
|
|
+ return playVideoWhenFlyOut//true
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
- update(player){
|
|
|
-
|
|
|
- if(player.mode == 'panorama'){//实时监测播放
|
|
|
- if(this.texType == "video"){
|
|
|
- if(this.visible && !this.pausedByUser && this.inSight()){
|
|
|
- this.videoControl(true)
|
|
|
- }else{
|
|
|
- this.videoControl(false)
|
|
|
- }
|
|
|
- }else if(this.info.animateInfo){
|
|
|
- if(this.visible && this.inSight()){
|
|
|
- GifTexDeal.start(this.animation)
|
|
|
- }else{
|
|
|
- GifTexDeal.stop(this.animation)
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
+ update(player){
|
|
|
+
|
|
|
if(this.info.isSprite){
|
|
|
this.quaternion.copy(player.camera.quaternion)
|
|
|
}
|
|
|
|
|
|
this.updateScale()
|
|
|
+ this.updateTitle()
|
|
|
}
|
|
|
|
|
|
updateScale(e, t) {//自适应调节大小
|
|
|
- if(!DATA.autoAdjustHotScale || this.texType != 'shine' )return
|
|
|
+ if(!DATA.autoAdjustHotScale || this.texType != 'shine' || !this.plane )return
|
|
|
//let renderSize = player.sceneRenderer.renderer.domElement
|
|
|
let renderSize = player.sceneRenderer.renderer.getSize()
|
|
|
|
|
@@ -954,33 +948,62 @@ window.initHot = function(model){
|
|
|
|
|
|
}
|
|
|
|
|
|
+ loadVideo(video){
|
|
|
+ if(video.src)return
|
|
|
+ video.src = manage.dealURL(this.info.texSrc);
|
|
|
+ }
|
|
|
|
|
|
|
|
|
videoControl(state){
|
|
|
if(this.texType != "video" || !this.material_.map)return
|
|
|
var video = this.material_.map.image
|
|
|
+ this.shouldPlay = state
|
|
|
+
|
|
|
if(!state || state == 'stop'){
|
|
|
if(!video.paused){
|
|
|
video.pause()
|
|
|
- //console.log("pause " + this.sid)
|
|
|
+ console.log("pause " + this.sid)
|
|
|
}
|
|
|
|
|
|
if(state == 'stop'){
|
|
|
video.currentTime = 0;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
+ }
|
|
|
}else if(state){
|
|
|
if(video.paused){
|
|
|
+ this.loadVideo(video)
|
|
|
video.play()
|
|
|
- //console.log("play " + this.sid)
|
|
|
+ this.changeOpaWhenPlay(video)
|
|
|
+
|
|
|
+ console.log("play " + this.sid)
|
|
|
}
|
|
|
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
+ changeOpaWhenPlay(video){//当播放成功后,恢复为不透明
|
|
|
+ if(isNaN(video.duration)){//未加载好
|
|
|
+ return setTimeout(()=>{
|
|
|
+ this.changeOpaWhenPlay(video)
|
|
|
+ },100)
|
|
|
+ }
|
|
|
+ const minPlayedTime = Math.min(video.duration/10, 0.1); //到这个时间说明加载成功
|
|
|
+ if(!video.hasInitedOpacity){
|
|
|
+ setTimeout(e=>{
|
|
|
+ if(video.currentTime>minPlayedTime){
|
|
|
+ this.material_.opacity = 1
|
|
|
+ video.hasInitedOpacity = true
|
|
|
+ console.log('changeOpaWhenPlay',this.sid)
|
|
|
+ }else{
|
|
|
+ if(!video.paused){//再次尝试
|
|
|
+ return setTimeout(()=>{
|
|
|
+ this.changeOpaWhenPlay(video)
|
|
|
+ },500)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },minPlayedTime*1000+500)
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
|
@@ -988,45 +1011,49 @@ window.initHot = function(model){
|
|
|
var w = DATA.hotIconScale) * g_HotMeshSize.g_HotMeshWidth
|
|
|
this.scale.set( w, w, this.scale.z)
|
|
|
} */
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- setTitleElem(){
|
|
|
- var root = $("#hot");
|
|
|
- var title = this.info.title;
|
|
|
+
|
|
|
+
|
|
|
+ setTitleElem(){
|
|
|
+ var title = this.info.title;
|
|
|
if(title){
|
|
|
- if(!this.titleElem){
|
|
|
- var elem = $(`<div></div>`)
|
|
|
- root.append(elem);
|
|
|
- this.titleElem = elem;
|
|
|
- }
|
|
|
- this.titleElem.text(title)
|
|
|
+ if(!this.titleElem){
|
|
|
+ this.titleElem = new Label2D({position:this.position, innerHTML:`<div>${title}</div>`, domElement:$("#hot")[0], shelterByModel:true })
|
|
|
+ }else{
|
|
|
+ this.titleElem.elem.html(`<div>${title}</div>`)
|
|
|
+ }
|
|
|
+ this.titleElem.setVisible(this.visible, 'hotVisible')
|
|
|
+ this.setHoverState(false)
|
|
|
+ this.setTitleDir()
|
|
|
}else{
|
|
|
if(this.titleElem){
|
|
|
- this.titleElem.remove()
|
|
|
+ this.titleElem.dispose()
|
|
|
this.titleElem = null;
|
|
|
}
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
|
|
|
- showTitle(){
|
|
|
- if(!this.titleElem)return;
|
|
|
- var pos = math.getPos2d(this.position, player.camera, $("#player")[0])
|
|
|
- if(pos.trueSide){//inSight
|
|
|
- this.titleElem.css( { "left" : `${pos.pos.x}px`, "top": `${pos.pos.y}px ` });
|
|
|
- this.titleElem.css("display","block");
|
|
|
- }else{
|
|
|
- this.titleElem.css("display","none");
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- hideTitle(){
|
|
|
- if(!this.titleElem)return;
|
|
|
- this.titleElem.css("display","none");
|
|
|
+ setTitleDir(){
|
|
|
+ this.titleElem && this.titleElem.elem.attr('pos',this.info.titlePos)
|
|
|
}
|
|
|
|
|
|
|
|
|
+ updateTitle(){
|
|
|
+ this.titleElem && this.titleElem.update()
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ setHoverState(state){
|
|
|
+ if(!this.titleElem)return
|
|
|
+ this.hovered = !!state
|
|
|
+
|
|
|
+ var v = this.info.titleShowType != 'unvisible' && (this.info.titleShowType == 'always' || this.hovered)
|
|
|
+ this.titleElem.setVisible(v, 'hoveredVisi')
|
|
|
+ //this.updateTitle()
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
closestPanoTowardTag(e, t) {
|
|
|
var i = []
|
|
@@ -1073,17 +1100,40 @@ window.initHot = function(model){
|
|
|
(pano)=>{//尽量正对hot
|
|
|
let dir = new THREE.Vector3(0,0,1).applyQuaternion(this.quaternion)
|
|
|
let dir2 = new THREE.Vector3().subVectors(pano.position, this.position).normalize();
|
|
|
- let s = dir.dot(dir2) * 10;
|
|
|
+ let s = dir.dot(dir2) * 60;
|
|
|
//console.log(pano.id + ":" + s)
|
|
|
return s
|
|
|
- }
|
|
|
-
|
|
|
+ }
|
|
|
);
|
|
|
|
|
|
|
|
|
+ /* var tanD = player.domElement.clientWidth / player.domElement.clientHeight * Math.tan((THREE.Math.degToRad(player.zoomFov/2))) ;
|
|
|
+ var goodDistance = overlay.width / 2 / tanD;
|
|
|
+ n.push(
|
|
|
+ function (pano) { //寻找正对着overlay的pano
|
|
|
+ var overlayDir = new THREE.Vector3(0,0,1).applyQuaternion(overlay.quaternion)
|
|
|
+ var v1 = overlayDir//.setY(0); 朝上的话set0会得到0,0,0 无法求angle
|
|
|
+ var v2 = pano.position.clone().sub(overlay.position)//.setY(0)
|
|
|
+ var angle = v1.angleTo(v2)
|
|
|
+ angles[pano.id] = angle;
|
|
|
+ angle = -angle * 100
|
|
|
+ return angle
|
|
|
+ },
|
|
|
+ function (pano) { //寻找正对着overlay的pano
|
|
|
+ var dis = pano.position.clone().distanceToSquared(overlay.position)
|
|
|
+ var goodDistance2 = goodDistance * Math.abs(Math.cos(angles[pano.id]))//考虑了倾斜角度后的最佳距离
|
|
|
+
|
|
|
+ var result = - 300 * Math.abs(dis-goodDistance2) / goodDistance2 //dis和goodDistance2差距越大分数越低
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+ ) */
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
var s = t.model.panos.sortByScore(i, n);
|
|
|
-
|
|
|
- return s && 0 < s.length && s[0].pano
|
|
|
+ console.log(s)
|
|
|
+ return s && 0 < s.length && s[0].item
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1092,7 +1142,20 @@ window.initHot = function(model){
|
|
|
|
|
|
examine(options={}) {
|
|
|
var openHot = this.info.link && this.info.actionType.openHot && !options.dontOpen
|
|
|
- var needExamine = options.examine || (!settings.dontExamHot && this.info.actionType.examine)
|
|
|
+ var fastTran = !options.dontFastTran && ( this.info.actionType.fastTran || settings.hotFastTran || options.fastTran)
|
|
|
+ if(fastTran){//瞬间过渡 1到固定方位 2到和普通过渡一样的位置,也就是最适合的位置
|
|
|
+ let info = this.info.cameraData
|
|
|
+ if(info){
|
|
|
+ player.blackToPano({
|
|
|
+ pano: player.model.panos.index[info.pano.uuid],
|
|
|
+ quaternion: new THREE.Quaternion().fromArray(info.camera.quaternion)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ var needExamine = !fastTran && (options.examine || (!settings.dontExamHot && this.info.actionType.examine))
|
|
|
if(!openHot && !needExamine)return;
|
|
|
|
|
|
|
|
@@ -1217,7 +1280,18 @@ window.initHot = function(model){
|
|
|
aimDuration: options.aimDuration,
|
|
|
|
|
|
};
|
|
|
- player.flyToPano(d, done)
|
|
|
+ if(fastTran){
|
|
|
+ let f = (new THREE.Matrix4).lookAt(c.position, h, new THREE.Vector3(0,1,0));
|
|
|
+ let quaternion = (new THREE.Quaternion).setFromRotationMatrix(f)
|
|
|
+ player.blackToPano({
|
|
|
+ pano:c,
|
|
|
+ quaternion,
|
|
|
+ })
|
|
|
+ done()
|
|
|
+ }else{
|
|
|
+ player.flyToPano(d, done)
|
|
|
+ }
|
|
|
+
|
|
|
} else {
|
|
|
var p = {
|
|
|
pano: c
|
|
@@ -1344,12 +1418,14 @@ window.initHot = function(model){
|
|
|
} */
|
|
|
|
|
|
|
|
|
- requestDownload(type,callback) {
|
|
|
+ requestDownload(type, callback) {
|
|
|
var plane = this.plane;
|
|
|
|
|
|
if(type == 'photo'){
|
|
|
- if(this.photoHasRequestLoad || this.texType != 'photo')return;
|
|
|
- //console.log('overlay beginDownload : ' + this.sid)
|
|
|
+ if(this.photoHasRequestLoad || this.texType != 'photo'){
|
|
|
+ return; //为什么之前1191需要在这加callback() 才能呢。现在又没事了
|
|
|
+ }
|
|
|
+ //console.log(' beginDownload : ' + this.sid)
|
|
|
|
|
|
|
|
|
/* this.material_.map = */Texture.load(this.info.texSrc, (tex)=>{
|
|
@@ -1357,7 +1433,9 @@ window.initHot = function(model){
|
|
|
if(!tex.image ){
|
|
|
return //只是单纯用了相同src的tex,但image仍未加载完
|
|
|
}
|
|
|
- if(!this._loadDones)return
|
|
|
+ if(!this._loadDones){
|
|
|
+ return
|
|
|
+ }
|
|
|
dealMap(tex)
|
|
|
|
|
|
setTimeout(Hot.loadNext, 50)
|
|
@@ -1391,6 +1469,7 @@ window.initHot = function(model){
|
|
|
}
|
|
|
if(!finded){
|
|
|
let tex_ = tex.clone();
|
|
|
+ tex_.needsUpdate = true //clone后不写这句会黑块
|
|
|
animateTexSrcs[e.info.texSrc].set(e.info.animateInfo, tex_)
|
|
|
e.material_.map = tex_
|
|
|
}
|
|
@@ -1418,7 +1497,7 @@ window.initHot = function(model){
|
|
|
{
|
|
|
e._loadDones.forEach(a=>a())
|
|
|
e._loadDones = null
|
|
|
- e.photoHasRequestLoad = true
|
|
|
+ //e.photoHasRequestLoad = true //这句不能加,否则会无法执行callback
|
|
|
}
|
|
|
e.material_.needsUpdate = true
|
|
|
|
|
@@ -1452,7 +1531,15 @@ window.initHot = function(model){
|
|
|
|
|
|
this.modelHasRequestLoad = true
|
|
|
}
|
|
|
- }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ dispose(){
|
|
|
+ this.parent.remove(this)
|
|
|
+ this.titleElem && this.titleElem.dispose()
|
|
|
+ delete player.model.hots[this.sid]
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1491,10 +1578,11 @@ window.initHot = function(model){
|
|
|
let count = Hot.maxLoadingCount - loadings.length
|
|
|
Hot.loadQueue.slice(0, count).forEach(e=>{
|
|
|
loadings.push(e)
|
|
|
- //console.log(e)
|
|
|
+ //console.log('requestDownload', e.hot.info.texSrc)
|
|
|
e.hot.requestDownload(e.type, ()=>{
|
|
|
var i = loadings.indexOf(e)
|
|
|
- loadings.splice(i,1)
|
|
|
+ //console.log('requestDownloaded index', i)
|
|
|
+ i > -1 && loadings.splice(i,1)
|
|
|
})
|
|
|
})
|
|
|
Hot.loadQueue.splice(0, count)
|
|
@@ -1575,6 +1663,8 @@ window.initHot = function(model){
|
|
|
else{
|
|
|
Hot.load()
|
|
|
}
|
|
|
+
|
|
|
+ setTimeout(Hot.beginShineHot, 1000)
|
|
|
}
|
|
|
window.Hot = Hot
|
|
|
|
|
@@ -1624,6 +1714,7 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
Hot.createHotList = function() {
|
|
|
+ if(!window.DATA.showHotListSta)return
|
|
|
var docFragment = document.createDocumentFragment();
|
|
|
var hots = hotGroup.children.filter(hot=>hot.info.actionType.openHot);
|
|
|
hots = hots.sort((a,b)=>{return a.order - b.order});
|
|
@@ -1636,13 +1727,114 @@ window.initHot = function(model){
|
|
|
li.appendChild(span);
|
|
|
docFragment.appendChild(li);
|
|
|
|
|
|
- })
|
|
|
- var ul = document.querySelector('#hotListContent ul');
|
|
|
- ul && ul.appendChild(docFragment);
|
|
|
+ })
|
|
|
+ setTimeout(()=>{
|
|
|
+ var ul = document.querySelector('#hotListContent ul');
|
|
|
+ ul && ul.appendChild(docFragment);
|
|
|
+ },3000) //部分安卓手机的钉钉和支付宝浏览器如果立即添加到列表会卡住
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ Hot.mobileAutoPlay = function(player){//移动端。不这么写video不会播放 . (2022.11.29: 可为何加了Hot.updateHots之后又会自动播了?https有关?
|
|
|
+ if(browser.isMobile()){
|
|
|
+ hotGroup.children.forEach((hot)=>{
|
|
|
+ /* if(hot.texType == 'video' && hot.shouldPlay){
|
|
|
+ console.log(1)
|
|
|
+ } */
|
|
|
+ if(!hot.clickToPlayInited && hot.texType == 'video' && hot.material_.map.image.paused && hot.shouldPlay){
|
|
|
+ //hot.update(player)
|
|
|
+ //console.log('clickToPlayInited111')
|
|
|
+ hot.videoControl(true)
|
|
|
+
|
|
|
+ if(!hot.material_.map.image.paused){
|
|
|
+ console.log('clickToPlayInited')
|
|
|
+ hot.changeOpaWhenPlay(video)
|
|
|
+ hot.clickToPlayInited = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ Hot.updateHots = function(){
|
|
|
+ for(var i in player.model.hots){
|
|
|
+ player.model.hots[i].update(player)
|
|
|
+ }
|
|
|
+
|
|
|
+ if(player.mode != 'panorama' || !player.ready)return
|
|
|
+
|
|
|
+ common.intervalTool.isWaiting('updateHots', ()=>{ //延时update,防止卡顿
|
|
|
+ let videoCanPlay = [], aniCanPlay = [];
|
|
|
+ for(var i in player.model.hots){
|
|
|
+
|
|
|
+ let hot = player.model.hots[i]
|
|
|
+
|
|
|
+
|
|
|
+ {//实时监测播放
|
|
|
+ if(hot.texType == "video" && !player.flying){ //飞行时不判断
|
|
|
+ if(hot.visible && !hot.pausedByUser && hot.inSight()){ //注意edit时insight一直为true
|
|
|
+ //this.videoControl(true)
|
|
|
+ videoCanPlay.push(hot)
|
|
|
+ }else{
|
|
|
+ hot.videoControl(false)
|
|
|
+ }
|
|
|
+ }else if(hot.info.animateInfo){
|
|
|
+ if(hot.visible && hot.inSight()){
|
|
|
+ aniCanPlay.push(hot)
|
|
|
+ }else{
|
|
|
+ GifTexDeal.stop(hot.animation)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let filter = (type,max,list,playFun)=>{
|
|
|
+ if(list.length < max){
|
|
|
+ list.forEach(hot=>type == 'video' ? hot.videoControl(true) : GifTexDeal.start(hot.animation))
|
|
|
+ }else{
|
|
|
+ let r = common.sortByScore(list,[],[(hot)=>{
|
|
|
+ let score = 0
|
|
|
+ var cornerPointInfo = hot.getCornerPoint(); //仅支持漫游模式
|
|
|
+ let pos2dSum = 0 //越接近0越接近屏幕中心
|
|
|
+ for(let i=1,j=cornerPointInfo.cornerPoint.length;i<j;i++){//忽略第一个点,那是中心点
|
|
|
+ var pos2d = math.getPos2d(cornerPointInfo.cornerPoint[i], player.camera, $("#player")[0])
|
|
|
+ if(pos2d.trueSide){
|
|
|
+ pos2dSum += Math.abs(pos2d.vector.x);
|
|
|
+ pos2dSum += Math.abs(pos2d.vector.y);
|
|
|
+ }else{
|
|
|
+ pos2dSum += 2-Math.abs(pos2d.vector.x); //感觉决定背面的只有x,所以忽略y?
|
|
|
+ }
|
|
|
+ }
|
|
|
+ let area = cornerPointInfo.diffLon * cornerPointInfo.diffLat //占据面积
|
|
|
+ score = -pos2dSum * (type == 'video' ? 100 : 10) + area //gif的面积权重增加些,也就是不一定要靠近中心。因为一般而言gif比较小,起指示作用,即使散落在四角也尽量闪烁;而视频要观看的话一般会凑近居于中心
|
|
|
+ return score
|
|
|
+ }])
|
|
|
+ //console.log(r)
|
|
|
+ r && r.forEach((e,j)=>{
|
|
|
+ let hot = e.item
|
|
|
+ if(j<max){
|
|
|
+ type == 'video' ? hot.videoControl(true) : GifTexDeal.start(hot.animation)
|
|
|
+ }else{
|
|
|
+ type == 'video' ? hot.videoControl(false) : GifTexDeal.stop(hot.animation)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ filter('video',playVideoMax, videoCanPlay);
|
|
|
+ filter('animateInfo',playAniMax, aniCanPlay);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }, 300)
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1665,4 +1857,9 @@ window.initHot = function(model){
|
|
|
数据速率为1824kbps,720 *576px 时正常
|
|
|
所以尽量降到2000以下 同时播放个数最好不超过2个 可能需要将src归零 并延迟加载、不自动播放
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ 有遇到某张图在ios里显示不出,但在ps重新输出后就可以。这张图的dpi高达500,不知道是否与此有关。
|
|
|
+
|
|
|
*/
|