|
@@ -4,16 +4,17 @@ g_currentHot = null
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+let texLoader
|
|
|
|
|
|
|
|
|
|
const playVideoWhenFlyOut = false
|
|
const playVideoWhenFlyOut = false
|
|
//同时可播放的最大个数:
|
|
//同时可播放的最大个数:
|
|
-const playVideoMax = window.isEdit ? 3 : browser.isMobile() ? 1 : 2;
|
|
|
|
|
|
+const playVideoMax = window.isEdit ? 3 : browser.isMobile() ? 1 : 3;
|
|
const playAniMax = window.isEdit ? 6 : browser.isMobile() ? 3 : 5;
|
|
const playAniMax = window.isEdit ? 6 : browser.isMobile() ? 3 : 5;
|
|
|
|
|
|
-
|
|
|
|
|
|
+/* const playSyncGroup = [//需要播放同步的视频。 每次都单独定制
|
|
|
|
+ // ['okh1UR466371', 'LGmLHP2615503' , 'VNyBI6614896'] //中,左,右 场景SHANGJJ
|
|
|
|
+] */
|
|
|
|
|
|
window.initHot = function(model){
|
|
window.initHot = function(model){
|
|
|
|
|
|
@@ -55,15 +56,13 @@ window.initHot = function(model){
|
|
|
|
|
|
var animateTexSrcs = {}
|
|
var animateTexSrcs = {}
|
|
|
|
|
|
- var getLink = function(link){
|
|
|
|
|
|
+ var getLink = function(link){
|
|
var src = '';
|
|
var src = '';
|
|
- var r = link.substring(link.indexOf("html") + 4),
|
|
|
|
- o = "en" == manage.number("lang") ? "&lang=" + manage.number("lang") : "";
|
|
|
|
- -1 == r.indexOf("?") ? src = link + "?time=" + randomTime().getTime() + "&id=" + window.number + o : src = link + "&time=" + randomTime().getTime() + "&id=" + window.number + o
|
|
|
|
- return src.replace('https://www.4dmodel.com/SuperTwo/hot_online1', 'hot')
|
|
|
|
- // return 'http://localhost:8080/#/?m=LgPwshB140290&time=1729214195550&id=TEST'
|
|
|
|
- // return src //打包
|
|
|
|
-
|
|
|
|
|
|
+ var r = link.substring(link.indexOf("html") + 4)
|
|
|
|
+ , o = "en" == manage.number("lang") ? "&lang=" + manage.number("lang") : "";
|
|
|
|
+ -1 == r.indexOf("?") ? src = link + "?time=" + randomTime().getTime() + "&id=" + window.number + o : src = link + "&time=" + randomTime().getTime() + "&id=" + window.number + o
|
|
|
|
+
|
|
|
|
+ return src
|
|
}
|
|
}
|
|
var removeSrcPostMark = function(url){//去除texture.load时自动加上的'?'
|
|
var removeSrcPostMark = function(url){//去除texture.load时自动加上的'?'
|
|
var index = url.indexOf('?')
|
|
var index = url.indexOf('?')
|
|
@@ -185,14 +184,17 @@ window.initHot = function(model){
|
|
}
|
|
}
|
|
|
|
|
|
this.transformAtPanos = transformAtPanos */
|
|
this.transformAtPanos = transformAtPanos */
|
|
|
|
+
|
|
|
|
+ //2024.3.18恢复transformAtPanos三个属性,isSprite优先级高于quaternion, 全局的热点大小改变不会影响当前有transformAtPanos的大小
|
|
|
|
+
|
|
//在每个漫游点独立设置的position。
|
|
//在每个漫游点独立设置的position。
|
|
var curPanoTransform = this.info.transformAtPanos[ getTransformSid()] || {}
|
|
var curPanoTransform = this.info.transformAtPanos[ getTransformSid()] || {}
|
|
|
|
|
|
|
|
|
|
//没有单独设置position的漫游点使用的position
|
|
//没有单独设置position的漫游点使用的position
|
|
this.position.copy(curPanoTransform.pos || info.position)
|
|
this.position.copy(curPanoTransform.pos || info.position)
|
|
- this.rotation.copy(info.rotation)
|
|
|
|
- this.scale.copy(info.scale)
|
|
|
|
|
|
+ this.quaternion.copy(curPanoTransform.quaternion || info.quaternion)
|
|
|
|
+ this.scale.copy(curPanoTransform.scale || info.scale)
|
|
|
|
|
|
this.changeTexType(info.texType, media)
|
|
this.changeTexType(info.texType, media)
|
|
|
|
|
|
@@ -226,7 +228,12 @@ window.initHot = function(model){
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ //设置visibles floor------------------
|
|
|
|
+ if(window.isEdit)this.setVisiblePanos();
|
|
|
|
+ else this.getFloor() //可能需要分批计算
|
|
|
|
+
|
|
|
|
|
|
|
|
+ //------------------------------------
|
|
|
|
|
|
/* if(this.info.modelBound){
|
|
/* if(this.info.modelBound){
|
|
this.mesh.updateMatrixWorld()
|
|
this.mesh.updateMatrixWorld()
|
|
@@ -294,7 +301,7 @@ window.initHot = function(model){
|
|
//是否开启多边形偏移 //ie不开启时blank也不会闪烁
|
|
//是否开启多边形偏移 //ie不开启时blank也不会闪烁
|
|
polygonOffsetFactor: -0.9,
|
|
polygonOffsetFactor: -0.9,
|
|
//多边形偏移因子
|
|
//多边形偏移因子
|
|
- polygonOffsetUnits: -4.0,
|
|
|
|
|
|
+ polygonOffsetUnits: -4.0,
|
|
//多边形偏移单位
|
|
//多边形偏移单位
|
|
}))
|
|
}))
|
|
|
|
|
|
@@ -372,7 +379,7 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
|
video.volume = 0
|
|
video.volume = 0
|
|
- video.muted = true
|
|
|
|
|
|
+ video.muted = true
|
|
video.currentTime = 0
|
|
video.currentTime = 0
|
|
|
|
|
|
|
|
|
|
@@ -509,9 +516,10 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
|
if(info.quaternion){
|
|
if(info.quaternion){
|
|
- info.rotation = new THREE.Euler().setFromVector3(convertValue(info.quaternion, THREE.Quaternion ))
|
|
|
|
|
|
+ info.quaternion = convertValue(info.quaternion, THREE.Quaternion )
|
|
}else{
|
|
}else{
|
|
- info.rotation = new THREE.Euler().setFromVector3(convertValue(info.rotation, THREE.Vector3 )) //热点的旧数据很多是字符串
|
|
|
|
|
|
+ info.rotation = convertValue(info.rotation, THREE.Vector3 )
|
|
|
|
+ info.quaternion = new THREE.Quaternion().setFromEuler( new THREE.Euler().setFromVector3(info.rotation)) //热点的旧数据很多是字符串
|
|
}
|
|
}
|
|
|
|
|
|
var s = Hot.getDefaulScale(info.hotIconScale) //旧版的大小,统一转换成新版
|
|
var s = Hot.getDefaulScale(info.hotIconScale) //旧版的大小,统一转换成新版
|
|
@@ -536,7 +544,7 @@ window.initHot = function(model){
|
|
|
|
|
|
delete info.media
|
|
delete info.media
|
|
|
|
|
|
- info.rotation = new THREE.Euler().setFromQuaternion(convertValue(info.qua, THREE.Quaternion ))
|
|
|
|
|
|
+ info.quaternion = convertValue(info.qua, THREE.Quaternion)
|
|
info.position = info.pos
|
|
info.position = info.pos
|
|
delete info.pos;
|
|
delete info.pos;
|
|
delete info.qua;
|
|
delete info.qua;
|
|
@@ -554,7 +562,7 @@ window.initHot = function(model){
|
|
delete info.file
|
|
delete info.file
|
|
}else{
|
|
}else{
|
|
|
|
|
|
- info.rotation = new THREE.Euler().fromArray(info.rotation)//.setFromVector3(info.rotation)
|
|
|
|
|
|
+ info.quaternion = new THREE.Quaternion().setFromEuler(new THREE.Euler().fromArray(info.rotation))//.setFromVector3(info.rotation)
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -584,14 +592,15 @@ window.initHot = function(model){
|
|
//为了兼容旧数据,尽量和hot的数据靠近,最后保存在hot里
|
|
//为了兼容旧数据,尽量和hot的数据靠近,最后保存在hot里
|
|
info.position = convertValue(info.position, THREE.Vector3)
|
|
info.position = convertValue(info.position, THREE.Vector3)
|
|
info.scale = convertValue(info.scale, THREE.Vector3)
|
|
info.scale = convertValue(info.scale, THREE.Vector3)
|
|
- delete info.quaternion
|
|
|
|
|
|
+ delete info.rotation //暂时不用,只有保存时才存为roration
|
|
|
|
|
|
info.linkType = info.linkType || "common"
|
|
info.linkType = info.linkType || "common"
|
|
|
|
|
|
|
|
|
|
for (let i in info.transformAtPanos) {
|
|
for (let i in info.transformAtPanos) {
|
|
info.transformAtPanos[i].pos = new THREE.Vector3().fromArray(info.transformAtPanos[i].pos)
|
|
info.transformAtPanos[i].pos = new THREE.Vector3().fromArray(info.transformAtPanos[i].pos)
|
|
- //info.transformAtPanos[i].qua = new THREE.Quaternion().fromArray(info.transformAtPanos[i].qua)
|
|
|
|
|
|
+ info.transformAtPanos[i].qua && (info.transformAtPanos[i].qua = new THREE.Quaternion().fromArray(info.transformAtPanos[i].qua))
|
|
|
|
+ info.transformAtPanos[i].scale && (info.transformAtPanos[i].scale = new THREE.Vector3().fromArray(info.transformAtPanos[i].scale))
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -641,9 +650,77 @@ window.initHot = function(model){
|
|
}*/
|
|
}*/
|
|
|
|
|
|
setVisiblePanos(visibleData){
|
|
setVisiblePanos(visibleData){
|
|
- if(visibleData)this.info.visiblePanos = visibleData
|
|
|
|
- else if(!this.info.visiblePanos) this.getVisiblePanos()
|
|
|
|
|
|
+ if(visibleData){
|
|
|
|
+ this.info.visiblePanos = visibleData
|
|
|
|
+ }else if(!this.info.visiblePanos){
|
|
|
|
+ this.getVisiblePanos()
|
|
|
|
+ }
|
|
|
|
+ this.getFloor()
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ getFloor(){//用于飞出后分层展示。最好只属于一个楼层,且是贴得最近的
|
|
|
|
+ //先直接向下探测
|
|
|
|
+ //不准的话再向四周选三个方向,以及visiblePanos,来加成求分
|
|
|
|
+ if(player.model.floors.list.length <= 1)return
|
|
|
|
+ if(this.floorByRay){
|
|
|
|
+ return this.floor = this.floorByRay //重复getFloor的话,因模型不会变,用ray得到的floor不会变
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let result
|
|
|
|
+ if(this.floorByRay !== false){
|
|
|
|
+ let map = new Map
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ let downVec = new THREE.Vector3(0,-1,0)
|
|
|
|
+
|
|
|
|
+ let pos = this.info.transformAtPanos.outSide?.pos || this.position
|
|
|
|
+ let centerPos
|
|
|
|
+ if(!this.plane){
|
|
|
|
+ let bound = new THREE.Box3().copy(this.info.modelBound.bound)
|
|
|
|
+ let center = bound.center()
|
|
|
|
+ let qua = this.info.transformAtPanos.outSide?.qua || this.quaternion
|
|
|
|
+ let scale = this.info.transformAtPanos.outSide?.scale || this.scale
|
|
|
|
+
|
|
|
|
+ var matrixWorld = new THREE.Matrix4().compose(pos, qua, scale)
|
|
|
|
+ matrixWorld.multiplyMatrices(matrixWorld, this.mesh.matrix)
|
|
|
|
+ centerPos = center.applyMatrix4(matrixWorld);
|
|
|
|
+ }else{
|
|
|
|
+ centerPos = pos
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let request = [(floor)=>{
|
|
|
|
+ player.raycaster.set(centerPos, downVec)
|
|
|
|
+ let n = player.raycaster.intersectObjects(floor.collider.children , true );
|
|
|
|
+ if(n && n[0]){
|
|
|
|
+ map.set(floor, n[0].distance)
|
|
|
|
+ return true
|
|
|
|
+ }
|
|
|
|
+ }]
|
|
|
|
+ let rank = [(floor)=>{
|
|
|
|
+ return - map.get(floor)
|
|
|
|
+ }]
|
|
|
|
+
|
|
|
|
+ result = common.sortByScore(player.model.floors.list, request, rank)
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+ if(result){
|
|
|
|
+ this.floor = this.floorByRay = result[0].item
|
|
|
|
+ }else{
|
|
|
|
+ this.floorByRay = false //标记 使用ray无法找到
|
|
|
|
+ console.warn('热点通过raycaster没有找到楼层', this)
|
|
|
|
+
|
|
|
|
+ if(this.info.visiblePanos){
|
|
|
|
+ let floorIndex = this.info.visiblePanos.map(e=>player.model.panos.index[e].floorIndex).sort()[Math.floor(this.info.visiblePanos.length/2)]//中位数
|
|
|
|
+ this.floor = player.model.floors.index[floorIndex]
|
|
|
|
+ console.log('热点根据visiblePanos找到楼层', this, this.floor.name)
|
|
|
|
+ }else{
|
|
|
|
+ this.floor = null
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
getVisiblePanos(){//在不同点还不一样
|
|
getVisiblePanos(){//在不同点还不一样
|
|
var depth = this.hasBox ? this.scale.z : 0;
|
|
var depth = this.hasBox ? this.scale.z : 0;
|
|
@@ -677,14 +754,14 @@ window.initHot = function(model){
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
- var getPos = (position)=>{//每个overlay位置对应5个坐标,plane中心和四个角的位置
|
|
|
|
|
|
+ var getPos = (position, quaternion=this.info.quaternion, scale=this.info.scale)=>{//每个overlay位置对应5个坐标,plane中心和四个角的位置
|
|
if(this.plane){
|
|
if(this.plane){
|
|
return cornerPoint.map(e=>{
|
|
return cornerPoint.map(e=>{
|
|
- return e.clone().applyEuler(this.info.rotation).add(position)
|
|
|
|
|
|
+ return e.clone().applyQuaternion(this.info.quaternion).add(position)
|
|
})
|
|
})
|
|
|
|
|
|
}else{
|
|
}else{
|
|
- var matrixWorld = new THREE.Matrix4().compose(position, this.quaternion, this.scale)
|
|
|
|
|
|
+ var matrixWorld = new THREE.Matrix4().compose(position, quaternion, scale)
|
|
matrixWorld.multiplyMatrices(matrixWorld, this.mesh.matrix)
|
|
matrixWorld.multiplyMatrices(matrixWorld, this.mesh.matrix)
|
|
|
|
|
|
return cornerPoint.map(e=>{
|
|
return cornerPoint.map(e=>{
|
|
@@ -701,7 +778,8 @@ window.initHot = function(model){
|
|
|
|
|
|
for(let panoId in this.info.transformAtPanos){
|
|
for(let panoId in this.info.transformAtPanos){
|
|
if(panoId == 'outSide')continue;
|
|
if(panoId == 'outSide')continue;
|
|
- posAtPanos[panoId] = getPos(this.info.transformAtPanos[panoId].pos )
|
|
|
|
|
|
+ let {pos,qua,scale} = this.info.transformAtPanos[panoId]
|
|
|
|
+ posAtPanos[panoId] = getPos(pos,qua,scale)
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -710,9 +788,15 @@ window.initHot = function(model){
|
|
let maxCount = browser.isMobile() ? 2000 : 5000
|
|
let maxCount = browser.isMobile() ? 2000 : 5000
|
|
|
|
|
|
let possiblePanos = model.panos.list
|
|
let possiblePanos = model.panos.list
|
|
- if(this.plane){//目前都是单面,所以只要可以看到的一面的热点
|
|
|
|
- let dir1 = new THREE.Vector3(0,0,-1).applyQuaternion(this.quaternion).negate()
|
|
|
|
|
|
+ if(this.plane && !this.info.isSprite){//目前都是单面,所以只要可以看到的一面的热点
|
|
|
|
+ let defaultDir = new THREE.Vector3(0,0,-1).applyQuaternion(this.info.quaternion).negate()
|
|
possiblePanos = possiblePanos.filter(pano=>{
|
|
possiblePanos = possiblePanos.filter(pano=>{
|
|
|
|
+ let dir1
|
|
|
|
+ if(this.info.transformAtPanos[pano.id]?.qua){
|
|
|
|
+ dir1 = new THREE.Vector3(0,0,-1).applyQuaternion(this.info.transformAtPanos[pano.id].qua).negate()
|
|
|
|
+ }else{
|
|
|
|
+ dir1 = defaultDir
|
|
|
|
+ }
|
|
let dir2 = new THREE.Vector3().subVectors(pano.position, this.position).normalize();
|
|
let dir2 = new THREE.Vector3().subVectors(pano.position, this.position).normalize();
|
|
return dir1.dot(dir2)>0
|
|
return dir1.dot(dir2)>0
|
|
})
|
|
})
|
|
@@ -722,8 +806,7 @@ window.initHot = function(model){
|
|
if(window.isEdit || c < maxCount){ //编辑页面保险起见还是全部算完后才可浏览,就能保证保存全部的visiblePano
|
|
if(window.isEdit || c < maxCount){ //编辑页面保险起见还是全部算完后才可浏览,就能保证保存全部的visiblePano
|
|
this.info.visiblePanos = common.getVisiblePano(customPositions, possiblePanos , {
|
|
this.info.visiblePanos = common.getVisiblePano(customPositions, possiblePanos , {
|
|
model: model.colliders , posAtPanos
|
|
model: model.colliders , posAtPanos
|
|
- })
|
|
|
|
-
|
|
|
|
|
|
+ })
|
|
}else{
|
|
}else{
|
|
let start = 0
|
|
let start = 0
|
|
let interval = setInterval(()=>{
|
|
let interval = setInterval(()=>{
|
|
@@ -740,6 +823,7 @@ window.initHot = function(model){
|
|
|
|
|
|
if(end>=possiblePanos.length){
|
|
if(end>=possiblePanos.length){
|
|
//console.log(window.hotsi ?(++window.hotsi): (window.hotsi = 1))
|
|
//console.log(window.hotsi ?(++window.hotsi): (window.hotsi = 1))
|
|
|
|
+ this.getFloor() //re get
|
|
clearInterval(interval)
|
|
clearInterval(interval)
|
|
}
|
|
}
|
|
}, Hot.visiEveryDurSlice )// visiEveryDurSlice 等在main中定义
|
|
}, Hot.visiEveryDurSlice )// visiEveryDurSlice 等在main中定义
|
|
@@ -747,14 +831,21 @@ window.initHot = function(model){
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
|
|
- updateVisible(panos, visibility) {
|
|
|
|
- if(window.isEdit && editTool.hotpoint.editSpot == this){
|
|
|
|
- return this.visible = true
|
|
|
|
|
|
+ updateVisible(panos, visibility, type) {
|
|
|
|
+ if(window.isEdit && editTool.hotpoint.editSpot == this || player.mode != 'panorama' && visibility !== false){
|
|
|
|
+ return convertTool.updateVisible(this,'visi',true)
|
|
}
|
|
}
|
|
|
|
|
|
- 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')
|
|
|
|
|
|
+ let visible = visibility != void 0 ? visibility : (!this.info.visiblePanos ||
|
|
|
|
+ (type == 'every' ? panos.every(pano=>this.info.visiblePanos.includes(pano.id)) : panos.some(pano=>this.info.visiblePanos.includes(pano.id))))//type为every时,需要panos中每个都可见才显示
|
|
|
|
+
|
|
|
|
+ convertTool.updateVisible(this,'visi',visible)
|
|
|
|
+
|
|
|
|
+ this.titleElem && this.titleElem.setVisible(this.visible, 'hotVisible', 1)
|
|
|
|
+
|
|
|
|
+
|
|
|
|
|
|
if (this.texType == 'video'){
|
|
if (this.texType == 'video'){
|
|
//this.switchPlay(this.visible, this.visible ? null : 'stop' );//可见时不操作;不可见时停止
|
|
//this.switchPlay(this.visible, this.visible ? null : 'stop' );//可见时不操作;不可见时停止
|
|
@@ -973,13 +1064,13 @@ window.initHot = function(model){
|
|
this.updateTitle()
|
|
this.updateTitle()
|
|
}
|
|
}
|
|
|
|
|
|
- updateScale(e, t) {//自适应调节大小
|
|
|
|
|
|
+ updateScale(e, t) {//自适应调节大小
|
|
if(!DATA.autoAdjustHotScale || this.texType != 'shine' || !this.plane )return
|
|
if(!DATA.autoAdjustHotScale || this.texType != 'shine' || !this.plane )return
|
|
-
|
|
|
|
|
|
+
|
|
var scale = convertTool.getScaleForConstantSize($.extend({},autoSizeInfo,{
|
|
var scale = convertTool.getScaleForConstantSize($.extend({},autoSizeInfo,{
|
|
position: this.position.clone()
|
|
position: this.position.clone()
|
|
}))
|
|
}))
|
|
- this.plane.scale.set(scale,scale,scale)
|
|
|
|
|
|
+ this.plane.scale.set(scale,scale,scale) //修改mesh,和自定义修改的scale不冲突
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1001,29 +1092,39 @@ window.initHot = function(model){
|
|
if(this.texType != "video" || !this.material_.map)return
|
|
if(this.texType != "video" || !this.material_.map)return
|
|
var video = this.texMedia
|
|
var video = this.texMedia
|
|
this.shouldPlay = state
|
|
this.shouldPlay = state
|
|
-
|
|
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+
|
|
if(!state || state == 'stop'){
|
|
if(!state || state == 'stop'){
|
|
if(!video.paused){
|
|
if(!video.paused){
|
|
video.pause()
|
|
video.pause()
|
|
- console.log({str: "paused " + this.sid, level:1})
|
|
|
|
|
|
+ if(!video.muted){
|
|
|
|
+ SoundManager.pause('hot', true)//自动播放被中断的音频 (bgm
|
|
|
|
+ }
|
|
|
|
+ //console.log({str: "paused " + this.sid, level:1})
|
|
}
|
|
}
|
|
/* video.lastCurTime = state == 'stop' ? 0 : video.currentTime //记录
|
|
/* video.lastCurTime = state == 'stop' ? 0 : video.currentTime //记录
|
|
- video.src = video.src_ = '' */
|
|
|
|
-
|
|
|
|
|
|
+ video.src = video.src_ = '' */
|
|
if(state == 'stop'){
|
|
if(state == 'stop'){
|
|
video.currentTime = 0;
|
|
video.currentTime = 0;
|
|
}
|
|
}
|
|
}else if(state){
|
|
}else if(state){
|
|
if(/* !isVideoPlayed(video) */ video.paused ){
|
|
if(/* !isVideoPlayed(video) */ video.paused ){
|
|
- console.log({str: 'videoControl play ' +", "+ this.sid, level:1})
|
|
|
|
|
|
+ //console.log({str: 'videoControl play ' +", "+ this.sid, level:1})
|
|
this.loadVideo(video)
|
|
this.loadVideo(video)
|
|
video.play()
|
|
video.play()
|
|
|
|
+ if(!video.muted){
|
|
|
|
+ SoundManager.play('hot') //暂停bgm等
|
|
|
|
+ }
|
|
//video.currentTime = video.lastCurTime || 0
|
|
//video.currentTime = video.lastCurTime || 0
|
|
this.changeOpaWhenPlay(video)
|
|
this.changeOpaWhenPlay(video)
|
|
-
|
|
|
|
- if(isVideoPlayed(video))console.log({str:"played " + this.sid + video.duration ,level:1})
|
|
|
|
|
|
+
|
|
|
|
+ //处理同步播放
|
|
|
|
+ let group = playSyncGroup.find(e=>e.includes(this.sid))
|
|
|
|
+ if(group){
|
|
|
|
+ let others = group.filter(e=>e != this.sid).map(e=>player.model.hots[e].texMedia)
|
|
|
|
+ //console.log('controlVideo play', this.id, 'other currentTime', others.map(e=>e.currentTime))
|
|
|
|
+ video.currentTime = others[0].currentTime
|
|
|
|
+ }
|
|
|
|
+ //if(isVideoPlayed(video))console.log({str:"played " + this.sid + video.duration ,level:1})
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
@@ -1100,7 +1201,7 @@ window.initHot = function(model){
|
|
this.hovered = !!state
|
|
this.hovered = !!state
|
|
|
|
|
|
var v = this.info.titleShowType != 'unvisible' && (this.info.titleShowType == 'always' || this.hovered)
|
|
var v = this.info.titleShowType != 'unvisible' && (this.info.titleShowType == 'always' || this.hovered)
|
|
- this.titleElem.setVisible(v, 'hoveredVisi')
|
|
|
|
|
|
+ this.titleElem.setVisible(v, 'hoveredVisi', 1)
|
|
//this.updateTitle()
|
|
//this.updateTitle()
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1182,7 +1283,7 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
|
var s = t.model.panos.sortByScore(i, n);
|
|
var s = t.model.panos.sortByScore(i, n);
|
|
- console.log(s)
|
|
|
|
|
|
+ //console.log(s)
|
|
return s && 0 < s.length && s[0].item
|
|
return s && 0 < s.length && s[0].item
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1193,14 +1294,21 @@ window.initHot = function(model){
|
|
examine(options={}) {
|
|
examine(options={}) {
|
|
var openHot = this.info.link && this.info.actionType.openHot && !options.dontOpen
|
|
var openHot = this.info.link && this.info.actionType.openHot && !options.dontOpen
|
|
var fastTran = !options.dontFastTran && ( this.info.actionType.fastTran || settings.hotFastTran || options.fastTran)
|
|
var fastTran = !options.dontFastTran && ( this.info.actionType.fastTran || settings.hotFastTran || options.fastTran)
|
|
- if(fastTran){//瞬间过渡 1到固定方位 2到和普通过渡一样的位置,也就是最适合的位置
|
|
|
|
|
|
+ if(fastTran){//瞬间过渡 1到固定方位 2到和普通过渡一样的位置,也就是最适合的位置
|
|
let info = this.info.cameraData
|
|
let info = this.info.cameraData
|
|
if(info){
|
|
if(info){
|
|
player.blackToPano({
|
|
player.blackToPano({
|
|
pano: player.model.panos.index[info.pano.uuid],
|
|
pano: player.model.panos.index[info.pano.uuid],
|
|
quaternion: new THREE.Quaternion().fromArray(info.camera.quaternion)
|
|
quaternion: new THREE.Quaternion().fromArray(info.camera.quaternion)
|
|
})
|
|
})
|
|
- }
|
|
|
|
|
|
+ }else{
|
|
|
|
+ let pano = this.closestPanoTowardTag(player.mode, player.currentPano) || player.currentPano,
|
|
|
|
+ pos = this.mesh.getWorldPosition(),
|
|
|
|
+ m = (new THREE.Matrix4).lookAt(pano.position, pos, new THREE.Vector3(0,1,0)),
|
|
|
|
+ quaternion = new THREE.Quaternion().setFromRotationMatrix(m)
|
|
|
|
+
|
|
|
|
+ player.blackToPano({pano,quaternion})
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1392,7 +1500,7 @@ window.initHot = function(model){
|
|
this.mesh.modelBound = this.info.modelBound
|
|
this.mesh.modelBound = this.info.modelBound
|
|
|
|
|
|
}
|
|
}
|
|
- this.material_.side = THREE.FrontSide
|
|
|
|
|
|
+ this.material_.side = THREE.DoubleSide //模型单面的话不好校准位置
|
|
this.changeBoxHelperDisplay(false)
|
|
this.changeBoxHelperDisplay(false)
|
|
//this.mesh.boxHelper.visible = true
|
|
//this.mesh.boxHelper.visible = true
|
|
|
|
|
|
@@ -1409,7 +1517,7 @@ window.initHot = function(model){
|
|
delete this.info.modelBound
|
|
delete this.info.modelBound
|
|
|
|
|
|
this.setMesh(this.plane)
|
|
this.setMesh(this.plane)
|
|
- //this.material_.side = THREE.DoubleSide //双面的话飞出来会看到悬空的
|
|
|
|
|
|
+ this.material_.side = THREE.FrontSide //双面的话飞出来会看到热点悬空的
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1417,7 +1525,7 @@ window.initHot = function(model){
|
|
setMesh(mesh){
|
|
setMesh(mesh){
|
|
this.mesh = mesh
|
|
this.mesh = mesh
|
|
this.add(this.mesh);
|
|
this.add(this.mesh);
|
|
-
|
|
|
|
|
|
+
|
|
this.changeMaterial(this.material_) //re applyTo every mesh
|
|
this.changeMaterial(this.material_) //re applyTo every mesh
|
|
|
|
|
|
this.mesh.traverse((mesh)=>{
|
|
this.mesh.traverse((mesh)=>{
|
|
@@ -1435,22 +1543,21 @@ window.initHot = function(model){
|
|
this.mesh.boxHelper = new THREE.Box3Helper( bound, new THREE.Color( "#00ffff"));
|
|
this.mesh.boxHelper = new THREE.Box3Helper( bound, new THREE.Color( "#00ffff"));
|
|
this.mesh.add(this.mesh.boxHelper)
|
|
this.mesh.add(this.mesh.boxHelper)
|
|
this.mesh.boxHelper.material.depthTest = false;
|
|
this.mesh.boxHelper.material.depthTest = false;
|
|
- this.mesh.boxHelper.material.transparent = true
|
|
|
|
- this.mesh.boxHelper.visible = false
|
|
|
|
|
|
+ this.mesh.boxHelper.material.transparent = true
|
|
}
|
|
}
|
|
|
|
+ convertTool.updateVisible(this.mesh.boxHelper,'defaultHide', false)//默认隐藏
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
- changeBoxHelperDisplay(show){
|
|
|
|
- if(show){
|
|
|
|
- this.visible_ = this.visible
|
|
|
|
- this.visible = true
|
|
|
|
- this.mesh.boxHelper.visible = true
|
|
|
|
|
|
+ changeBoxHelperDisplay(show,reason='hover'){
|
|
|
|
+ if(show){//暂时先把模型强制显示,以展示 boxHelper
|
|
|
|
+ convertTool.updateVisible(this, 'showBoxHelper', true, 2, 'add')
|
|
|
|
+ convertTool.updateVisible(this.mesh.boxHelper, 'highlight_'+reason, true, 2, 'add')
|
|
|
|
+
|
|
}else{
|
|
}else{
|
|
- if(this.visible_ != void 0){
|
|
|
|
- this.visible = this.visible_
|
|
|
|
- }
|
|
|
|
- this.mesh.boxHelper.visible = false
|
|
|
|
|
|
+ convertTool.updateVisible(this, 'showBoxHelper', false, 2, 'cancel')
|
|
|
|
+ convertTool.updateVisible(this.mesh.boxHelper, 'highlight_'+reason, false, 2, 'cancel')
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
}
|
|
@@ -1472,9 +1579,8 @@ window.initHot = function(model){
|
|
return; //为什么之前1191需要在这加callback() 才能呢。现在又没事了
|
|
return; //为什么之前1191需要在这加callback() 才能呢。现在又没事了
|
|
}
|
|
}
|
|
//console.log(' beginDownload : ' + this.sid)
|
|
//console.log(' beginDownload : ' + this.sid)
|
|
-
|
|
|
|
|
|
|
|
- /* this.material_.map = */Texture.load(this.info.texSrc, (tex)=>{
|
|
|
|
|
|
+ Texture.load(this.info.texSrc, (tex)=>{
|
|
callback && callback()
|
|
callback && callback()
|
|
if(!tex.image ){
|
|
if(!tex.image ){
|
|
return //只是单纯用了相同src的tex,但image仍未加载完
|
|
return //只是单纯用了相同src的tex,但image仍未加载完
|
|
@@ -1499,6 +1605,7 @@ window.initHot = function(model){
|
|
if(window.isEdit){
|
|
if(window.isEdit){
|
|
if(animateTexSrcs[e.info.texSrc]){
|
|
if(animateTexSrcs[e.info.texSrc]){
|
|
e.material_.map = tex.clone(); //编辑动画直接不用一个texture, 故而animation也不同
|
|
e.material_.map = tex.clone(); //编辑动画直接不用一个texture, 故而animation也不同
|
|
|
|
+ e.material_.map.repeat.set(1,1), e.material_.map.offset.set(0,0)
|
|
e.material_.map.needsUpdate = true
|
|
e.material_.map.needsUpdate = true
|
|
|
|
|
|
}else{
|
|
}else{
|
|
@@ -1515,6 +1622,8 @@ window.initHot = function(model){
|
|
}
|
|
}
|
|
if(!finded){
|
|
if(!finded){
|
|
let tex_ = tex.clone();
|
|
let tex_ = tex.clone();
|
|
|
|
+ tex_.repeat.set(1,1), tex_.offset.set(0,0)
|
|
|
|
+
|
|
tex_.needsUpdate = true //clone后不写这句会黑块
|
|
tex_.needsUpdate = true //clone后不写这句会黑块
|
|
animateTexSrcs[e.info.texSrc].set(e.info.animateInfo, tex_)
|
|
animateTexSrcs[e.info.texSrc].set(e.info.animateInfo, tex_)
|
|
e.material_.map = tex_
|
|
e.material_.map = tex_
|
|
@@ -1560,11 +1669,10 @@ window.initHot = function(model){
|
|
|
|
|
|
}else if(type == 'model'){
|
|
}else if(type == 'model'){
|
|
if(this.modelHasRequestLoad || !this.info.objSrc)return;
|
|
if(this.modelHasRequestLoad || !this.info.objSrc)return;
|
|
-
|
|
|
|
- //需要处理重复?
|
|
|
|
|
|
+
|
|
objLoader.load(this.info.objSrc, (object)=>{
|
|
objLoader.load(this.info.objSrc, (object)=>{
|
|
this.remove(this.mesh)
|
|
this.remove(this.mesh)
|
|
- this.addModel(object)
|
|
|
|
|
|
+ this.addModel(object) //复制的也包含boxHelper(也是复制的)
|
|
|
|
|
|
callback && callback()
|
|
callback && callback()
|
|
if(++modelLoaded == originModelCount){//data2.js中的所有photo加载完毕
|
|
if(++modelLoaded == originModelCount){//data2.js中的所有photo加载完毕
|
|
@@ -1589,11 +1697,11 @@ window.initHot = function(model){
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- Hot.updateVisibles = function(panos) { //只显示没被遮挡的,否则会卡
|
|
|
|
|
|
+ Hot.updateVisibles = function(panos, type) { //只显示没被遮挡的,否则会卡
|
|
if (panos === true) {
|
|
if (panos === true) {
|
|
- model.hotGroup.children.forEach(e=>e.updateVisible(null,true))
|
|
|
|
|
|
+ model.hotGroup.children.forEach(e=>e.updateVisible(null,true,type))
|
|
} else {
|
|
} else {
|
|
- model.hotGroup.children.forEach(e=>e.updateVisible(panos))
|
|
|
|
|
|
+ model.hotGroup.children.forEach(e=>e.updateVisible(panos, null, type))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -1712,10 +1820,51 @@ window.initHot = function(model){
|
|
|
|
|
|
setTimeout(Hot.beginShineHot, 1000)
|
|
setTimeout(Hot.beginShineHot, 1000)
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if(!window.isEdit){
|
|
|
|
+ if(playSyncGroup.length){
|
|
|
|
+ //每过一段时间校准同步视频的时间,使与第一个视频同步
|
|
|
|
+ setInterval(()=>{
|
|
|
|
+
|
|
|
|
+ playSyncGroup.forEach(group=>{
|
|
|
|
+ group = group.map(e=>player.model.hots[e].texMedia).filter(e=>!e.paused)
|
|
|
|
+ if(group.length < 2)return
|
|
|
|
+ //console.log('同步',group.map(e=>e.currentTime))
|
|
|
|
+ for(let i=group.length-1;i>0;i--){
|
|
|
|
+ group[i].currentTime = group[0].currentTime
|
|
|
|
+ }
|
|
|
|
+ })
|
|
|
|
+
|
|
|
|
+ },4000)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
player.emit('gotHotAndStartload')
|
|
player.emit('gotHotAndStartload')
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if(player.model.floors.list.length>1){
|
|
|
|
+ player.model.on("floor.changed",(currentFloor, mode, oldFloor)=>{
|
|
|
|
+ //this.update(currentFloor) //注: currentFloor 这时候还没成为 model.currentFloor
|
|
|
|
+ let showAll = mode == 'panorama' || player.model.allFloorsVisible
|
|
|
|
+ hotGroup.children.forEach(e=>{
|
|
|
|
+ convertTool.updateVisible(e,'floor',showAll || e.floor == currentFloor)
|
|
|
|
+ })
|
|
|
|
+ //console.log(currentFloor, mode, oldFloor)
|
|
|
|
+ })
|
|
|
|
+ }
|
|
|
|
+
|
|
}
|
|
}
|
|
|
|
+
|
|
window.Hot = Hot
|
|
window.Hot = Hot
|
|
-
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
/* var ball = new THREE.Mesh(new THREE.SphereBufferGeometry(0.01),new THREE.MeshBasicMaterial({color:"#f00",depthTest:false,transparent:true}))
|
|
/* var ball = new THREE.Mesh(new THREE.SphereBufferGeometry(0.01),new THREE.MeshBasicMaterial({color:"#f00",depthTest:false,transparent:true}))
|
|
var balls = []
|
|
var balls = []
|
|
var addPoint = function(point){
|
|
var addPoint = function(point){
|
|
@@ -1762,13 +1911,10 @@ window.initHot = function(model){
|
|
|
|
|
|
|
|
|
|
Hot.createHotList = function() {
|
|
Hot.createHotList = function() {
|
|
- // if(!window.DATA.showHotListSta)return
|
|
|
|
|
|
+ //if(!window.DATA.showHotListSta)return
|
|
var docFragment = document.createDocumentFragment();
|
|
var docFragment = document.createDocumentFragment();
|
|
var hots = hotGroup.children.filter(hot=>hot.info.actionType.openHot);
|
|
var hots = hotGroup.children.filter(hot=>hot.info.actionType.openHot);
|
|
hots = hots.sort((a,b)=>{return a.order - b.order});
|
|
hots = hots.sort((a,b)=>{return a.order - b.order});
|
|
-
|
|
|
|
- window.myHotList = hots
|
|
|
|
-
|
|
|
|
hots.forEach((hot)=>{
|
|
hots.forEach((hot)=>{
|
|
var li = document.createElement('li');
|
|
var li = document.createElement('li');
|
|
var span = document.createElement('span');
|
|
var span = document.createElement('span');
|
|
@@ -1926,6 +2072,8 @@ function isVideoPlayed(video){
|
|
return !video.paused && !isNaN(video.duration) //注意,有的手机首次play时会立即paused为false,但其实没加载好, duration为NAN
|
|
return !video.paused && !isNaN(video.duration) //注意,有的手机首次play时会立即paused为false,但其实没加载好, duration为NAN
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
/*
|
|
/*
|
|
|
|
|
|
|
|
|
|
@@ -1951,4 +2099,11 @@ function isVideoPlayed(video){
|
|
遇到过ios14.8.1、14.7.1 无法播放webm(来自1050)。 onloadedmetadata失败
|
|
遇到过ios14.8.1、14.7.1 无法播放webm(来自1050)。 onloadedmetadata失败
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ 显示故障的机型:
|
|
|
|
+ 视频黑屏(4dkk视频漫游点也无法播放):小米10(自带浏览器)、红米K40(微信浏览器)、
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ 贴图safari黑色的,很可能是使用CMYK模式的原因,dpi>96了
|
|
*/
|
|
*/
|