'))
div.addClass('slider')
if (o.unitStr) {
div.find(".BarTxt").append($('
' + o.unitStr + ''));
}
o.root.append(div);
this.line = $(".scrollBar", div);
this.knot = $(".scroll_Thumb", div);
o.noValue || (this.textArea = $(".scrollBarTxt", div));
this.track = $(".scroll_Track", div);
this.unitStr = o.unitStr;
//unitStr是单位字符串,比如角度的°。不能是数字
this.onchange = o.onchange;
this.percent = null;
this.dragStart = false;
this.offsetToBody = null;
this.getOffset();
this.checkError();
this.percent = this.getPercent();
o.noValue || this.displayValue();
this.moveKnot();
this.knotWidth = 0;
this.lineWidth = 0;
//this.waitValue;//等待要触发事件的值,防止崩溃
this.avoidCrash = o.avoidCrash;
this.realMax = !this.noValue ? o.realMax : null;
//如果传入realMax,代表可以通过输入数字修改最大值范围,最大值不可以超过realMax。
this.scrollUnit = (scope.max - scope.min) * 0.001;
if (this.precision != void 0) {
var prec = Math.pow(10, -this.precision);
this.scrollUnit < prec && (this.scrollUnit = prec);
} else {
//默认化为整数
this.scrollUnit < 1 && (this.scrollUnit = 1);
}
this.dragStartEvent = o.dragStartEvent;
this.line.on("mousedown touchstart", function(event) {
scope.dragStart = true;
scope.dragChange(event);
if (scope.dragStartEvent)
scope.dragStartEvent()
//if(o.avoidCrash && isMobile)scope.dealInterval();
});
!window.isMobile && this.line.on("mousewheel DOMMouseScroll wheel", function(event) {
event.preventDefault();
var v = event.originalEvent.deltaY > 0 ? -scope.scrollUnit : scope.scrollUnit;
scope.setValue(scope.value + v);
});
this.dragEndEvent = o.dragEndEvent;
var stop = function() {
if (scope.dragStart) {
scope.dragStart = false;
if (scope.dragEndEvent)
scope.dragEndEvent()
}
}
$(document).on("mouseup touchend", stop)
/* isMobile || */
$("#player").on("mouseup", stop)
var lastChangeTime = 0;
$(document).on("mousemove touchmove", function() {
if (scope.dragStart) {
/* if(isMobile && o.avoidCrash){
scope.lastDragEvent = event;
}else */
scope.dragChange(event);
}
})
o.noValue || this.textArea.on("change", function() {
var v = parseFloat(scope.textArea.val());
if (v != v)
//NaN
return;
scope.setValueFromOutside(v);
});
window.addEventListener("resize",()=>{
if(this.line[0].clientWidth){
this.getOffset()
this.moveKnot();
}
})
}
SlideBar.prototype.dealInterval = function() {
this.interval = setInterval(function() {
this.lastDragEvent && this.dragChange(this.lastDragEvent);
this.lastDragEvent = null
if (!this.dragStart)
clearInterval(this.interval)
}
.bind(this), 90)
}
SlideBar.prototype.changeLimit = function(o) {
if (o.min)
this.min = o.min;
if (o.max)
this.max = o.max;
}
SlideBar.prototype.getOffset = function() {
//为了检测鼠标位置需要获得相对body的offset
var left = this.line[0].offsetLeft;
var element = this.line[0];
while (element = element.offsetParent) {
left += element.offsetLeft;
}
this.offsetToBody = (left == 0) ? (this.offsetToBody || 0) : left;
//如果left为0,很可能是它不可见,那么最好使用旧的offsetToBody
}
SlideBar.prototype.InitOffset = function() {
//如果一开始scroller没有显示,要在显示时获取一下offset
this.getOffset();
this.getWidth();
this.moveKnot();
}
SlideBar.prototype.checkError = function() {
if (this.min >= this.max) {
console.log("scrollbar值有误 " + name);
return;
}
}
SlideBar.prototype.getPercent = function() {
return (this.value - this.min) / (this.max - this.min);
}
SlideBar.prototype.displayValue = function(value) {
//this.textArea.val(this.value + (this.unitStr ? " " + this.unitStr : ""));
if (value != void 0)
this.value = value;
this.textArea.val(this.value)
}
SlideBar.prototype.getWidth = function() {
this.knotWidth = this.knot.width();
this.lineWidth = this.line.width() - this.knotWidth
}
SlideBar.prototype.moveKnot = function() {
//this.getWidth();
var width = this.percent * this.lineWidth;
this.knot.css('left', width + "px")
if (this.track)
this.track.css('width', (width + this.knotWidth / 2) + "px")
}
SlideBar.prototype.bind = function(f) {
this.onchange = f;
}
SlideBar.prototype.setValue = function(v, noEvent, changeMax) {
//设置数值并改变knot位置 noEvent为true的话就可以不触发回调函数,仅仅改变显示
//if(this.value==v)return; //因为换选材质需要执行后面onchange才会带动preview的改变,所以这里一样还是执行,而拉动滑动条的部分值不变就不执行
if (this.precision != void 0) {
this.value = parseFloat(v.toFixed(this.precision))
} else {
//默认化为整数
this.value = Math.round(v);
}
if (changeMax && this.realMax != void 0) {
if (this.value > this.oriMax) {
this.value = Math.min(this.value, this.realMax);
this.changeLimit({
max: this.value
})
} else {
this.changeLimit({
max: this.oriMax
})
}
}
this.percent = this.getPercent();
var makeit = true;
if (this.onchange && !noEvent) {
var result = this.onchange(this.value);
//如果执行的函数不允许这个值,就不能变
if (result === false) {
makeit = false;
}
}
if (makeit) {
this.moveKnot();
//console.log("SlideBarV-"+this.name + " : "+this.value)
this.noValue || this.displayValue();
}
}
SlideBar.prototype.dragChange = function(event) {
//拖动时触发 计算数值
//this.getWidth();
//if(!this.offsetToBody || isNaN(this.offsetToBody)this.getOffset();
if (event.clientX != void 0) {
this.percent = (event.clientX - this.knotWidth / 2 - this.offsetToBody) / this.lineWidth;
} else {
if (event.touches != void 0) {
this.percent = (event.touches[0].clientX - this.knotWidth / 2 - this.offsetToBody) / this.lineWidth;
} else
this.percent = (event.originalEvent.touches[0].clientX - this.knotWidth / 2 - this.offsetToBody) / this.lineWidth;
}
if (this.percent < 0)
this.percent = 0;
else if (this.percent > 1)
this.percent = 1;
//var v = this.percent * this.max;
var v = this.percent * (this.max - this.min) + this.min;
//var v = Math.round(this.percent * this.max * 10)/10; //精度为0.1
if (this.value == v)
return;
this.setValue(v);
}
SlideBar.prototype.setValueFromOutside = function(v) {
//外面的事件触发的
if (this.line.width() == 0)
return;
//不可见就不执行。
//v = Math.round(v*10)/10;
if (this.realMax != void 0) {
v = THREE.Math.clamp(v, this.min, this.realMax);
if (v > this.max)
this.changeLimit({
max: v
});
} else
v = THREE.Math.clamp(v, this.min, this.max);
this.setValue(v);
}
//-----------------------------------------------------
var LineDraw = {
createLine: function(posArr, o) {
var e = new THREE.BufferGeometry
, p = new Float32Array(6);
e.addAttribute("position", new THREE.BufferAttribute(p,3));
//这句新旧版写法不同 旧版这样:e.addAttribute("position",Float32Array,2,3);
var p = e.attributes.position.array;
for (var i = 0; i < 2; i++) {
p[i * 3] = posArr[i].x;
p[i * 3 + 1] = posArr[i].y;
p[i * 3 + 2] = posArr[i].z;
}
var mat = new THREE[o.deshed ? "LineDashedMaterial" : "LineBasicMaterial"]({
linewidth: o.width || 1,
//windows无效。 似乎mac/ios上粗细有效 ?
color: o.color || defaultColor,
transparent: o.dontAlwaysSeen ? false : true,
depthTest: o.dontAlwaysSeen ? true : false
})
var line = new THREE.Line(e,mat);
line.renderOrder = o.renderOrder || 4
//同tagStem; //如果不加高,可能会部分被model遮住
return line;
}
}
var toPrecision = function(e, t) {
function i(e, t) {
var i = Math.pow(10, t);
return Math.round(e * i) / i
}
if (e instanceof Array) {
for (var n = 0; n < e.length; n++)
e[n] = i(e[n], t);
return e
}
return i(e, t)
}
var transformControls;
var initTransformCtl = function(THREE) {
TransformControls.init(THREE)
TransformControls.prototype.transCtlChangeMode = function(mode) {
//if(!this.editing)return;
if (mode && this.mode != mode) {
this.mode = mode;
}
}
,
transformControls = new TransformControls(player.camera,player.domElement,{
player: player,
dontHideWhenFaceCamera: true,
scaleAxis: ["x", "y"],
//隐藏了z轴。虽然参数没用上
NoScaleZ: true //整体缩放时只缩放xy轴。
});
transformControls.space = 'local'//为了在当前方向上平移
transformControls.setSize(1.5)
player.model.add(transformControls)
$(".MenuOptions[name='transform'] li").on("click", (e)=>{
transformControls.transCtlChangeMode($(e.target).attr("index"))
})
}
var EditOverlay = {
editing: false,
overlayMaxCount: 10,
scroller: {
videoDepth: new SlideBar({
root: $('#videoDepth').eq(0),
value: settings.overlay.depth * 100,
min: 0 * 100,
max: 1 * 100,
name: "videoDepth",
unitStr: "cm",
avoidCrash: true,
onchange: function(s) {
if (s == 0) {
EditOverlay.editPlane.addBox(false)
} else {
EditOverlay.editPlane.addBox(true)
EditOverlay.editPlane.scale.z = s / 100 / settings.overlay.depth;
}
},
dragEndEvent: function() {
}
})
},
panoPosSwitch : $('#setOverlayPosForPano input') // 当前漫游点独立调整位置开关
,
init: function(THREE) {
var mat = new THREE.MeshBasicMaterial({
wireframe: true,
opacity: 0.5,
color: "#57e4f3",
transparent: true
})
var wireframeModel = this.wireframeModel = new THREE.Object3D;
wireframeModel.name = 'wireframeModel'
player.model.chunks.forEach((mesh)=>{
var chunk = mesh.clone();
chunk.material = mat;
wireframeModel.add(chunk)
}
)
wireframeModel.visible = false
player.model.add(wireframeModel)
//------------------------------
this.panoPosSwitch.on("change", this.panoPosSwitchOnChange.bind(this))
$('.overlay .addBtn button').on("click", this.beginToAddPlane.bind(this))
$("#overlayProp a.close").on("click", ()=>{
this.closeOverlayPanel("cancel")
}
)
$("#overlayProp button.submit").on("click", (e)=>{
this.SaveOverlay()
}
)
$("#overlayProp button.delete").on("click", (e)=>{
this.DeleteOverlay();
}
)
$('#overlayUpload [name="useImgRatio"] button').on("click", this.useImgRatio.bind(this));
var uploadInputs = {
video : $('
'),
photo : $('
')
}
$('#overlayUpload [name="upload"] button').on('click', ()=>{
uploadInputs[this.editType].click()
})
uploadInputs.video.on("change", (e)=>{
inputMedia({
enableTypes: [this.editType ],
videoDone: (file,video)=>{
var plane = this.editPlane.plane
$(video).css('width', '100%')
$(video).css('height', '100%')
plane.material.map = new THREE.VideoTexture(video);
plane.material.map.image.play();
plane.material.map.minFilter = THREE.LinearFilter;
this.editPlane.overlayType = "video";
$('#overlayUpload .preview video').remove();
//$('#overlayUpload .preview').css('background-image',"").append($(video));
video.autoplay = true;
video.loop = true;
video.volume = 0
video.muted = true
this.useImgRatio()
//自适应比例
this.editPlane.file = file;
plane.material.opacity = 1;
plane.material.color = new THREE.Color(1,1,1)
plane.material.needsUpdate = true;
}
}, "video", e);
}
)
uploadInputs.photo.on("change", (e)=>{
inputMedia({
enableTypes: [this.editType ],
photoDone: (photo)=>{
var plane = this.editPlane.plane
/* $(video).css('width', '100%')
$(video).css('height', '100%') */
plane.material.map = new THREE.Texture();
plane.material.map.image = photo
plane.material.map.needsUpdate = !0
plane.material.map.minFilter = THREE.LinearFilter;
this.editPlane.overlayType = "photo";
$('#overlayUpload .preview video').remove();
//$('#overlayUpload .preview').css('background-image',"").append($(video));
this.useImgRatio()
this.updateGifPanel(this.editPlane)
if(this.editPlane.animateInfo){
GifTexDeal.remove(this.editPlane.animation)
this.editPlane.animation = GifTexDeal.addAnimation(this.editPlane.plane.material.map, this.editPlane, this.editPlane.animateInfo, this.editPlane.sid)
GifTexDeal.start(this.editPlane.animation)
}
//自适应比例
this.editPlane.file = photo.file;
plane.material.opacity = 1;
plane.material.color = new THREE.Color(1,1,1)
plane.material.needsUpdate = true;
}
}, "photo", e);
}
)
player.overlayGroup.children.forEach((overlay)=>{
if(!overlay.plane.material.map || !overlay.plane.material.map.image){
overlay._loadDones = [()=>{this.getOverlayInfo(overlay)}]
}
else {
this.getOverlayInfo(overlay)
}
this.addToList(overlay)
} )
$("#gifSwitch input").on("change", (e)=>{
var on = $("#gifSwitch input").is(':checked');
$("#gifInfoEdit").css({display: on ? 'block' : 'none'})
if(on){
EditOverlay.editPlane.animateInfo = {
cellXcount : parseInt($("#gifXCount").val()),
cellYcount : parseInt($("#gifYCount").val()),
loop : true,
duration : parseFloat($("#gifDuration").val()) * 1000
}
EditOverlay.editPlane.animation = GifTexDeal.addAnimation(EditOverlay.editPlane.plane.material.map, EditOverlay.editPlane, EditOverlay.editPlane.animateInfo, EditOverlay.editPlane.sid)
GifTexDeal.start(EditOverlay.editPlane.animation)
}else{
GifTexDeal.remove(EditOverlay.editPlane.animation)
EditOverlay.editPlane.animateInfo = null
}
})
{//gif动画 input
let strictInputNum = function(e, precision, min=0,max){//precision:保留小数位数
var value = e.target.value.trim();
var lastOne = value[value.length-1];
var preContent = value.substr(0,value.length-1)
var hasPoint = precision > 0 && lastOne == '.' ;
var a = Math.pow(10, precision)
value = parseFloat(value) || 0;
if(isNaN(value)){
e.target.value = preContent //还原
return
}
e.target.value = Math.max(min, parseInt(value * a) / a )
hasPoint && (e.target.value += '.')//补小数点
}
let changeAnimation = function(){
GifTexDeal.setRepeart(EditOverlay.editPlane.animation)
}
let restartAnimation = function(){
GifTexDeal.stop(EditOverlay.editPlane.animation)
GifTexDeal.start(EditOverlay.editPlane.animation)
}
let changeFrameCount = function(){
var a = EditOverlay.editPlane.animateInfo
var frameCount = a.cellXcount * a.cellYcount
$("#gifFrameCount").text(frameCount)
var fps = parseFloat($("#gifFps").val())
a.duration = frameCount / fps * 1000
$("#gifDuration").val(toPrecision(a.duration/1000, 2))
}
let gifXCountFun = function(value){
EditOverlay.editPlane.animateInfo.cellXcount = value
var gifImgWidth = parseFloat($("#gifImgWidth").text())
var gifCellWidth = toPrecision(gifImgWidth / EditOverlay.editPlane.animateInfo.cellXcount,1);
$("#gifCellWidth").val(gifCellWidth)
changeFrameCount()
changeAnimation()
}
$("#gifXCount").on('input',(e)=>{
strictInputNum(e, 0)
gifXCountFun(parseFloat(e.target.value))
})
$("#gifXCount").on('change',(e)=>{
strictInputNum(e, 0, 1)
gifXCountFun(parseFloat(e.target.value))
restartAnimation()
})
let gifYCountFun = function(value){
EditOverlay.editPlane.animateInfo.cellYcount = value
var gifImgHeight = parseFloat($("#gifImgHeight").text())
var gifCellHeight = toPrecision(gifImgHeight / EditOverlay.editPlane.animateInfo.cellYcount,1);
$("#gifCellHeight").val(gifCellHeight)
changeFrameCount()
changeAnimation()
}
$("#gifYCount").on('input',(e)=>{
strictInputNum(e, 0)
gifYCountFun(parseFloat(e.target.value))
})
$("#gifYCount").on('change',(e)=>{
strictInputNum(e, 0, 1)
gifYCountFun(parseFloat(e.target.value))
changeAnimation()
restartAnimation()
})
let gifCellWidthFun = function(value){
var gifCellWidth = value;
var gifImgWidth = parseFloat($("#gifImgWidth").text())
var cellXcount = toPrecision(gifImgWidth / gifCellWidth,2);
$("#gifXCount").val(cellXcount)
changeAnimation()
}
$("#gifCellWidth").on('input',(e)=>{
strictInputNum(e, 0)
gifCellWidthFun(parseFloat(e.target.value))
})
$("#gifCellWidth").on('change',(e)=>{
strictInputNum(e, 0, 1)
gifCellWidthFun(parseFloat(e.target.value))
var cellXcount = $("#gifXCount").val();
var cellXcountInt = Math.round(cellXcount)
if(cellXcountInt != cellXcount){
$("#gifXCount").val(cellXcountInt)
gifXCountFun(cellXcountInt)
changeAnimation()
}
restartAnimation()
})
let gifCellHeightFun = function(value){
var gifCellHeight = parseFloat(e.target.value);
var gifImgHeight = parseFloat($("#gifImgHeight").text())
var cellYcount = toPrecision(gifImgHeight / gifCellHeight,2);
$("#gifYCount").val(cellYcount)
}
$("#gifCellHeight").on('input',(e)=>{
strictInputNum(e, 0)
gifCellHeightFun(parseFloat(e.target.value))
})
$("#gifCellHeight").on('change',(e)=>{
strictInputNum(e, 0, 1)
gifCellHeightFun(parseFloat(e.target.value))
var cellYcount = $("#gifYCount").val();
var cellYcountInt = Math.round(cellYcount)
if(cellYcountInt != cellYcount){
$("#gifYCount").val(cellYcountInt)
gifYCountFun(cellYcountInt)
changeAnimation()
}
restartAnimation()
})
let gifDurationFun = function(value){
var a = EditOverlay.editPlane.animateInfo
let frameCount = a.cellXcount * a.cellYcount
a.duration = value
$("#gifFps").val(toPrecision(frameCount / a.duration * 1000, 1))
}
$("#gifDuration").on('input',(e)=>{
strictInputNum(e, 1);
gifDurationFun(parseFloat(e.target.value) * 1000)
})
$("#gifDuration").on('change',(e)=>{
strictInputNum(e, 1, 0.01);
gifDurationFun(parseFloat(e.target.value) * 1000)
restartAnimation()
})
var gifFpsFun = function(e){
strictInputNum(e, 0, 1);
var fps = parseFloat(e.target.value)
var a = EditOverlay.editPlane.animateInfo
let frameCount = a.cellXcount * a.cellYcount
a.duration = frameCount / fps * 1000
$("#gifDuration").val(toPrecision(a.duration / 1000, 2))
}
$("#gifFps").on('input',(e)=>{
gifFpsFun(e)
})
$("#gifFps").on('change',(e)=>{
gifFpsFun(e)
restartAnimation()
})
}
},
enter: function() {
this.editing = true;
this.wireframeModel.visible = true;
},
leave: function() {
if (!this.editing)
return;
this.editing = false
$("#overlayProp a.close").click();
this.endAddPlane();
this.wireframeModel.visible = false;
},
switchEditType : function(type){
this.editType = type;
$('#overlayUpload [name="upload"] button').text(type == 'video' ? "上传视频" : "上传图片")
$('#overlayUpload .preview span').eq(0).text(type == 'video' ? "支持MP4、MOV等,<20M" : "支持jpg、png等,<20M");
if(type != 'photo' || !this.editPlane) $('#overlayProp #gifEdit').css({display: 'none'})
},
beginToAddPlane: function(event) {
this.switchEditType($(event.target).attr("data-type"))
player.reticule.visible = false;
this.objCursorType = 'overlay';
player.currentCursor = 'url(images/edit/box_video.png), auto'
$('#player').css('cursor', player.currentCursor)
$('.overlay .addBtn button').addClass("unable")
//可以加多个视频时的按钮
},
endAddPlane: function() {
this.objCursorType = null;
player.currentCursor = '';
$('#player').css('cursor', '')
$('.overlay .addBtn button').removeClass("unable")
player.reticule.visible = true
},
addPlane: function(o) {
if(!o.intersect)return;
var pos = o.intersect.point;
var overlay = new Overlay({
sid: new Date().getTime() + ""
})
overlay.hasRequestLoad = true
overlay.position.copy(pos);
if (player.getMouseDirection().angleTo(o.intersect.face.normal) < Math.PI / 2) {
overlay.lookAt(o.intersect.face.normal.clone().negate().add(pos));
overlay.position.add(o.intersect.face.normal.clone().negate().multiplyScalar(0.01))
//avoid mesh crash with chunks 模型的精度可能和floorplan的不一样,所以chunk即使材质经过处理还是会闪烁但是wallmesh不会
} else {
overlay.lookAt(o.intersect.face.normal.clone().add(pos));
overlay.position.add(o.intersect.face.normal.clone().multiplyScalar(0.01))
}
overlay.posCustom = overlay.position.clone();
overlay.quaCustom = overlay.quaternion.clone();
overlay.widthCustom = overlay.width;
overlay.heightCustom = overlay.height;
overlay.isNew = true
player.clickOverlay(overlay)
transformControls.transCtlChangeMode("translate")
this.addToList(overlay)
},
updateOverlayScaleDisplay: function() {
var overlay = this.editPlane;
var maxWidth = 193
, maxHeight = maxWidth
//maxWidth/2;
var ratioW = Math.abs(overlay.width) / maxWidth;
var ratioH = Math.abs(overlay.height) / maxHeight;
var ratio = 1 / Math.max(ratioW, ratioH);
//缩放比例
var w = Math.round(Math.abs(overlay.width) * ratio)
var h = Math.round(Math.abs(overlay.height) * ratio)
$('#overlayUpload .preview').css({
"width": w + 'px',
"height": h + 'px',
});
$('#overlayUpload .preview [attr-type="width"]').text(toPrecision(overlay.width, 2))
$('#overlayUpload .preview [attr-type="height"]').text(toPrecision(overlay.height, 2))
$("#gifSwitch input").prop('checked', !!overlay.animateInfo);
$("#gifInfoEdit").css({display: !!overlay.animateInfo ? 'block' : 'none'})
},
updateOverlayPreview : function(overlay){
var plane = overlay.plane
var src = plane.material.map && (plane.material.map.image ? plane.material.map.image.src : overlay.fileSrc );
$('#overlayUpload .preview video').remove();
if (overlay.overlayType == "video") {
var video = plane.material.map.image
$('#overlayUpload .preview').css({'background-image':"", 'background-size':""}).append(video);
} else if(overlay.overlayType == "photo" || overlay.overlayType == "text"){
$('#overlayUpload .preview').css({
'background-image': src ? ("url(" + src + ")") : "",
'background-size': "100% 100%"
})
}else{
$('#overlayUpload .preview').css({
'background-image': "",
'background-size': ""
})
}
if (overlay.overlayType) {
$('#overlayUpload [name="useImgRatio"]').removeClass("hide")
$('#overlayUpload .preview').addClass('uploaded')
} else {
$('#overlayUpload [name="useImgRatio"]').addClass("hide")
$('#overlayUpload .preview').removeClass('uploaded')
}
}
,
updateOverlayPanel: function(overlay) {
overlay.overlayType && this.switchEditType(overlay.overlayType)
this.updateOverlayPreview(overlay)
this.updateOverlayScaleDisplay()
this.updateGifPanel(overlay)
if (overlay.hasBox) {
this.scroller.videoDepth.setValue(overlay.scale.z * settings.overlay.depth * 100, true)
} else {
this.scroller.videoDepth.setValue(0, true)
}
setTimeout(()=>{
this.scroller.videoDepth.InitOffset()
}
, 201)
this.updatePano()
},
//----------------------------
updateGifPanel : function(overlay){
if(this.editType == 'photo'){
if(!overlay.plane.material.map)return;
$('#overlayProp #gifEdit').css({display: 'block'})
let w = overlay.plane.material.map.image.width
let h = overlay.plane.material.map.image.height
if(overlay.animateInfo){
let a = overlay.animateInfo
$("#gifXCount").val(a.cellXcount);
$("#gifYCount").val(a.cellYcount);
$("#gifImgWidth").text(w)
$("#gifImgHeight").text(h)
$("#gifCellWidth").val(toPrecision(w / a.cellXcount, 2));
$("#gifCellHeight").val(toPrecision(h / a.cellYcount, 2));
let frameCount = a.cellXcount * a.cellYcount
$("#gifFrameCount").text(frameCount)
$("#gifDuration").val(toPrecision(a.duration / 1000, 2));
$("#gifFps").val(toPrecision(frameCount / a.duration * 1000, 1) );
}else{
$("#gifXCount").val(1);
$("#gifYCount").val(1);
$("#gifImgWidth").text(w)
$("#gifImgHeight").text(h)
$("#gifCellWidth").val(w);
$("#gifCellHeight").val(h)
$("#gifFrameCount").text(1)
$("#gifDuration").val(1);
$("#gifFps").val(1);
}
}
}
,
beginEdit : function(overlay){
$('#overlayProp').removeClass('atRight').removeClass('hide')
this.endAddPlane();
this.editPlane = overlay;
overlay.requestDownload()
if(overlay._loadDones){
$('.waiting').addClass('showloading');
overlay._loadDones.push(()=>{
$('.waiting').removeClass('showloading');
})
}
overlay.visible = true
this.updateOverlayPanel(overlay)
transformControls.attach(overlay)
}
,
panoPosSwitchOnChange : function(){
var on = this.panoPosSwitch.is(':checked')
if(!on){
delete this.editPlane.transformAtPanos[getTransformSid()]
this.editPlane.position.copy(this.editPlane.posCustom)
this.editPlane.quaternion.copy(this.editPlane.quaCustom)
var scale = this.editPlane.getScaleBySize(this.editPlane.widthCustom, this.editPlane.heightCustom)
this.editPlane.scale.set(scale.x, scale.y, this.editPlane.scale.z)
//this.editPlane.usingTransformData = false
}
}
,
getTransformAtPano : function(){
var name = getTransformSid()
this.editPlane.transformAtPanos[name] = {
pos : this.editPlane.position.clone(),
qua : this.editPlane.quaternion.clone(),
width : this.editPlane.width,
height : this.editPlane.height,
}
//this.editPlane.usingTransformData = true
},
updatePosition:function(){
var on = this.panoPosSwitch.is(':checked')
if(on){
this.getTransformAtPano()
}else{
this.editPlane.posCustom.copy(this.editPlane.position)
}
},
updateScale : function(){
var on = this.panoPosSwitch.is(':checked')
var size = this.editPlane.getSizeByScale( )
this.editPlane.width = size.width
this.editPlane.height = size.height
if(on){
this.getTransformAtPano()
}else{
this.editPlane.widthCustom = this.editPlane.width
this.editPlane.heightCustom = this.editPlane.height
}
this.updateOverlayScaleDisplay()
}
,
updateQua : function(){
var on = this.panoPosSwitch.is(':checked')
if(on){
this.getTransformAtPano()
}else{
this.editPlane.quaCustom.copy(this.editPlane.quaternion)
}
}
,
updatePano:function(){
if(!EditOverlay.editPlane ) return;
this.panoPosSwitch.prop('checked', !!EditOverlay.editPlane.transformAtPanos[ getTransformSid()]);
},
//------------------------------
closeOverlayPanel: function(type) {
if (!this.editPlane)
return;
if (type == 'cancel') {
if (!this.editPlane.isNew && !this.editPlane.needDelete)
this.editPlane.setFromInfo(this.editPlane.info)
else
this.disposeOverlay(this.editPlane);
//删除
}
this.editPlane = null;
transformControls.detach()
$("#overlayProp").addClass("atRight");
//if(player.model.overlayPlanes.length < this.overlayMaxCount) this.beginToAddPlane()
},
useImgRatio: function(o) {
var plane = this.editPlane.plane;
if (!plane.material.map)
return;
var img = plane.material.map.image;
var mintranRatio = 200;
//default is 200 , 防止图片太小时在墙上依旧很大
var width = this.editPlane.overlayType == "video" ? img.videoWidth : img.width;
var height = this.editPlane.overlayType == "video" ? img.videoHeight : img.height;
if (o == "suitSize") {
var boundWidth = Math.min(Math.max(width, height) / mintranRatio, 1)
if (width > height) {
var w = boundWidth;
var h = boundWidth * height / width
} else {
var h = boundWidth;
var w = boundWidth * width / height;
}
} else {
//假设不变总面积
var k = Math.sqrt(Math.abs(this.editPlane.width * this.editPlane.height) / (width * height))
var w = k * width * (this.editPlane.width < 0 ? -1 : 1);
var h = k * height * (this.editPlane.height < 0 ? -1 : 1);
}
this.editPlane.scale.setX(w / settings.overlay.width)
this.editPlane.scale.setY(h / settings.overlay.height)
this.editPlane.width = w;
this.editPlane.height = h;
this.updateScale()
this.updateOverlayPreview(this.editPlane)
},
getOverlayInfo: function(overlay) {
//2 编辑前, 从当前状态获取info
var plane = overlay.plane;
var transformAtPanos = {}
for(var i in overlay.transformAtPanos){
transformAtPanos[i] = {
width : overlay.transformAtPanos[i].width,
height : overlay.transformAtPanos[i].height,
pos : overlay.transformAtPanos[i].pos.clone(),
qua : overlay.transformAtPanos[i].qua.clone(),
}
}
overlay.info = {
width: overlay.widthCustom,
height: overlay.heightCustom,
depth: settings.overlay.depth * overlay.scale.z,
pos: overlay.posCustom.clone(),
qua: overlay.quaCustom.clone(),
media: plane.material.map.image,
file: overlay.file,
type: overlay.overlayType,
hasBox: overlay.hasBox,
transformAtPanos: transformAtPanos
}
if(overlay.animateInfo ){
overlay.info.animateInfo = CloneObject(overlay.animateInfo)
}
},
getSavingInfo: function(overlay) {
if (!overlay.file && (!overlay.plane.material.map || !overlay.plane.material.map.image)) {
return;
}
var transformAtPanos = {}
for(var i in overlay.transformAtPanos){
transformAtPanos[i] = {
width : toPrecision(overlay.transformAtPanos[i].width, 4),
height : toPrecision(overlay.transformAtPanos[i].height, 4),
pos : toPrecision(overlay.transformAtPanos[i].pos.toArray(), 3),
qua : toPrecision(overlay.transformAtPanos[i].qua.toArray(), 5)
}
}
var info = {
width: toPrecision(overlay.widthCustom, 4),
height: toPrecision(overlay.heightCustom, 4),
depth: toPrecision(settings.overlay.depth * overlay.scale.z, 4),
pos: toPrecision(overlay.posCustom.toArray(), 3),
qua: toPrecision(overlay.quaCustom.toArray(), 5),
sid: overlay.sid,
hasBox: overlay.hasBox ? 1 : 0,
media: [overlay.overlayType],
file: overlay.fileSrc || overlay.plane.material.map.image.src,
transformAtPanos : transformAtPanos,
}
if(overlay.animateInfo && overlay.animateInfo.cellXcount * overlay.animateInfo.cellYcount > 1){
info.animateInfo = overlay.animateInfo
}
return info
},
SaveOverlay: function() {
var overlay = this.editPlane;
if (!overlay.file && (!overlay.plane.material.map || !overlay.plane.material.map.image)) {
this.editType == "video" ? alert("请上传视频") : alert("请上传图片");
return;
}
var saveInfo = ()=>{
//overlay.savingInfo = JSON.stringify(info)//准备写入的info
//saveDone:
overlay.isNew = false;
overlay.getVisiblePanos()
this.getOverlayInfo(overlay);
this.closeOverlayPanel()
$('.waiting').removeClass('showloading');
}
if (!overlay.info || overlay.file != overlay.info.file) {
$('.waiting').addClass('showloading');
uploadFile(overlay.file, 'overlay', function(rs) {
if (rs.code === 0) {
overlay.fileSrc = rs.data;
saveInfo()
}
;
})
} else
saveInfo();
},
disposeOverlay: function(overlay) {
var plane = overlay.plane
if (overlay == player.hoveringPlane) {
player.hoverOverlay(null, "soon");
}
if (plane.material.map) {//删除视频src
//overlay.info && common.destroyBlob(overlay.info.media.src)
//common.destroyBlob(plane.material.map.image.src)
}
plane.material.dispose();
overlay.parent.remove(overlay);
this.removeFromList(overlay)
if(this.animation){
GifTexDeal.remove(this.animation)
}
//this.beginToAddPlane()
},
DeleteOverlay: function() {
var overlay = this.editPlane;
if (!overlay.isNew) {
if (confirm(overlay.overlayType== "photo" ? "确定删除该图片?" : "确定删除该视频?")) {
overlay.needDelete = true;
$("#overlayProp a.close").click()
//this.closeOverlayPanel()
}
} else {
//刚创建时的删除按钮等同于取消按钮
$("#overlayProp a.close").click()
//this.closeOverlayPanel()
}
},
addToList: function(overlay) {
var li = $(`
${(overlay.overlayType == "video" ? "视频 ":"图片 ")+ overlay.sid}
`)
$(".overlayList ul").append(li);
li.on("click", ()=>{
player.clickOverlay(overlay)
player.focusPoint({aim: overlay.position})
})
overlay.domLi = li;
},
removeFromList: function(overlay) {
overlay.domLi.remove();
}
}
//----------------漫游可见性---------------------------------
var VisiSet = {
setPanoVisible: false,
setTagVisible: false,
panoVLines: {},
//线条
panoVTemp: {},
//修改后还没保存的临时数据
tagVsetting: null,
//正在设置的热点中心点
tagsVLines: {},
//线条
//tagVTemp //修改后还没保存的临时数据
$confirmSnap: $("#camera-start"),
changeBtn : $(".toolMid .midBottom #midBtns>button").eq(1),
colors: {
green: "#00c8ae"
},
init: function() {
this.footIconSizeRatio = Math.max(player.model.size.x, player.model.size.z) / 30;
this.meshGroup = new THREE.Object3D;
this.meshGroup.name = "setVisible-group"
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([e=>e.isAligned()], [(pano)=>{return -pano.position.distanceTo(this.panoVsetting.position)}])
if(list.length == 1){
console.log('仅有一个漫游点')
return;
}
var ifBlock = function(panoA, panoB ){
var A = panoA.position.clone();
var B = panoB.position.clone();
return convertTool.ifIntersectChunks(A, B, {})
}
var okList
var s = Math.max(-list[1].score*2, 4); //i==1的一定显示
for(var i=1;i
e.good && !e.block));//绝对可以使用的
if(okList.length <2 ){
if(!ifBlock(this.panoVsetting, list[i].pano)){
if(okList.length == 0){
okList.push(list[i])
}else{//1
var lastPos = okList[0].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)))
break;
}
}
}
}else{
break;
}
}
}
if(okList.length==0){//如果length为0,至少加一个pano, 虽然是遮挡的
okList.push(list[0].pano)
}
okList.forEach(e=>this.dealPanoVisible(e.pano.id))
console.log(okList)
}
})
},
enterSet: function(fun) {
var enter = function() {
if (player.modeTran.split('-')[1] != "floorplan") {
setTimeout(fun, 300)
//提前一点出现
}
player.flyToMode("floorplan", fun);
}
permitTranMode(false)
if (!player.modeTran) {
player.afterCModeFuc = ()=>{
enter()
}
} else
enter()
},
beginSetPanoLog: function() {
player.flying || $(".toolLeft").removeClass("unable")
if (this.setPanoLog)
return;
this.setPanoLog = true
this.panosSelect = []
this.updateFootIconSize()
this.showFootIcons(null, true);
for(let i in player.model.hots){
player.model.hots[i].visi_ = player.model.hots[i].mesh.visible;
player.model.hots[i].mesh.visible = false
}
player.model.panos.forEach(e=>{
e.addTextSprite(e.id, $('#panoIdColorTex').val())
})
},
finishSetPanoLog: function() {
//结束 退出这个设置
if (!this.setPanoLog)
return;
//否则会加多个侦听
this.setPanoLog = false;
this.hideFootIcons();
this.recoverAllState2();
this.panosSelect = null
player.flyoutType = null
permitTranMode(true)
for(let i in player.model.hots){
player.model.hots[i].mesh.visible = player.model.hots[i].visi_
}
$("#panosIdShow").val('')
player.model.panos.forEach(e=>{
e.removeTextSprite()
})
},
dealPanoLogClick: function(id) {
var panos = player.model.panos;
var index = this.panosSelect.indexOf(id)
if (index==-1) {
this.changeFIconState(panos.index[id].footIcon, "linked" )
this.panosSelect.push(id)
}else{
this.changeFIconState(panos.index[id].footIcon, false)
this.panosSelect.splice(index,1)
}
$("#panosIdShow").val(this.panosSelect.join(', '));
}
,
changePanoIdColor:function(color){
player.model.panos.forEach(e=>{
e.removeTextSprite();
e.addTextSprite(e.id,color)
})
}
,
beginSetPanoVisible: function() {
player.flying || $(".toolLeft").removeClass("unable")
if (this.setPanoVisible)
return;
this.setPanoVisible = true;
this.panoVTemp = {};
this.SetOnePanoVisible(player.currentPano)
//先设置currentPano
this.$confirmSnap.text('保存当前设置').removeClass("hide")
//objects.tagManager.hideAllTags();
this.setDisplay(true)
this.updateFootIconSize()
//更新一下大小,尤其是上次换了中心点然后退出又进入但是镜头没有变化的话
for(let i in player.model.hots){
player.model.hots[i].visi_ = player.model.hots[i].mesh.visible;
player.model.hots[i].mesh.visible = false
}
},
SetOnePanoVisible: function(pano) {
//点击某个pano后就对该pano点进行设置
if (this.panoVsetting == pano)
return;
//if (this.panoVsetting) saveLastPanoVi(this.panoVsetting);
this.panoVsetting = pano;
//记录正在修改的
this.delVisibleLines();
//删除线
this.showFootIcons(pano, true);
this.createPanoVisiLines(pano);
//创线
this.changeBtn.removeClass('hide')
},
saveLastPanoVi: function() {
//保存刚设置过的pano
var change = [];
for (var r in this.panoVLines) {
var line = this.panoVLines[r];
if (line.name.indexOf("new") > -1 && line.visible) {
//新设置为visible且没有取消
change.push({
type: "add",
id: r
})
} else if (line.name.indexOf("new") == -1 && !line.visible) {
//旧的且已经取消
change.push({
type: "sub",
id: r
})
}
}
if (change.length) {
//添加双向的neighbour:
var self = this.searchNeib(this.panoVsetting.id)
//var seeMarkers_self = self.seeMarkers;
var neighbourUUIDs_self = self.neighbourUUIDs
var neighbourPanos_self = self.neighbourPanos;
for (var i = 0; i < change.length; i++) {
var other = this.searchNeib(change[i].id)
//var seeMarkers = other.seeMarkers;
var neighbourUUIDs = other.neighbourUUIDs;
var neighbourPanos = other.neighbourPanos;
if (change[i].type == "add") {
//seeMarkers.push(this.panoVsetting.id);
neighbourUUIDs.push(this.panoVsetting.id);
neighbourPanos[this.panoVsetting.id] = true;
//seeMarkers_self.push(change[i].id);
neighbourUUIDs_self.push(change[i].id);
neighbourPanos_self[change[i].id] = true;
} else {
//var index = seeMarkers.indexOf(this.panoVsetting.id);
//index > -1 && seeMarkers.splice(index, 1);
var index = neighbourUUIDs.indexOf(this.panoVsetting.id);
index > -1 && neighbourUUIDs.splice(index, 1);
neighbourPanos[this.panoVsetting.id] = false;
//var index = seeMarkers_self.indexOf(change[i].id);
//index > -1 && seeMarkers_self.splice(index, 1);
var index = neighbourUUIDs_self.indexOf(change[i].id);
index > -1 && neighbourUUIDs_self.splice(index, 1);
neighbourPanos_self[change[i].id] = false;
}
this.panoVTemp[change[i].id] = {
//后面两个是作为保存到后台的数据存储,临时需要用到的是第一个
neighbourPanos: neighbourPanos,
//seeMarkers: seeMarkers,
neighbourUUIDs: neighbourUUIDs
}
}
this.panoVTemp[this.panoVsetting.id] = {
//加上自己
neighbourPanos: neighbourPanos_self,
//seeMarkers: seeMarkers_self,
neighbourUUIDs: neighbourUUIDs_self
}
}
},
pauseSetPanoVisible: function(type) {
//暂停 因为点击了保存设置 但没有退出设置
if (!this.setPanoVisible)
return;
if (type == "unsaved") {
//中途点击pano从而停止一个热点的设置
this.saveLastPanoVi();
} else {
this.panoVTemp = {};
//清空数据
}
this.delVisibleLines();
this.showFootIcons();
//清空选择
var lastPanoSetting = this.panoVsetting;
this.panoVsetting = null;
lastPanoSetting && this.changeFIconState2(lastPanoSetting.footIcon, this.checkHasNeighbor(lastPanoSetting))
//这句要放在this.panoVsetting = null后。 根据可见性更改透明度
this.changeBtn.addClass('hide')
},
//按理说改变了neighbourPano,tag的初始visible也要改。但是这样还要考虑已经改过的tag。。很麻烦
finishSetPanoVisible: function() {
//结束 退出这个设置
if (!this.setPanoVisible)
return;
//否则会加多个侦听
this.setPanoVisible = false;
this.hideFootIcons();
this.delVisibleLines();
//objects.tagManager.showAllTags();
this.recoverAllState2();
this.panoVsetting = null;
this.panoVTemp = {};
player.flyoutType = null
this.$confirmSnap.addClass("hide")
permitTranMode(true)
this.setDisplay(false)
for(let i in player.model.hots){
player.model.hots[i].mesh.visible = player.model.hots[i].visi_
}
},
changeVisiBtnState: function(state){
this.changeBtn.attr("function", state ? "hide" : "show")
this.changeBtn.html(state ? "隐藏该点位置":"显示该点位置")
},
recoverAllState2: function() {
//为了热点可视恢复成pano全部可见
if(!this.footIcons)return;
for (var i = 0; i < this.footIcons.length; i++) {
this.footIcons[i].material.uniforms.opacity.value = 1;
this.footIcons[i].material.uniforms.map.value = footTex1;
}
},
afterSavePanoVisibles: function() {
//实施:
var panos = player.model.panos;
for (var i in this.panoVTemp) {
var pano = panos.index[i];
//pano.seeMarkers = this.panoVTemp[i].seeMarkers;
pano.neighbourUUIDs = this.panoVTemp[i].neighbourUUIDs;
pano.neighbourPanos = this.panoVTemp[i].neighbourPanos;
}
if (!this.checkHasNeighbor(player.currentPano)) {
//currentPano变为孤立点 就要换一个防止飞入
var list = panos.sortByScore([pano=>{
return this.checkHasNeighbor(pano)
}
], [function(pano) {
return -pano.position.distanceTo(player.currentPano.position)
}
])
if (list && list.length) {
player.currentPano = list[0].pano;
//找最近的一非孤立点
//this.noPanoHasNeighbor = false; //更新状态
} else {//this.noPanoHasNeighbor = true; //更新状态
}
} else {//this.noPanoHasNeighbor = false; //更新状态
}
//dataDeal.done();
//暂时:
this.pauseSetPanoVisible()
this.updateFootIconSize()
//更新一下center大小 写在最后
},
//最佳推荐操作顺序: 先设置pano可见性 再创建热点 这样热点的visible正确些,否则之后再设置热点可见性会改更多
savePanoVisibles: function() {
//保存
if (this.panoVsetting)
this.saveLastPanoVi(this.panoVsetting);
//获取最后设置的那个热点的改动
var PanoData = [];
for (var i in this.panoVTemp) {
PanoData.push({
//希望算法部不会更改index排序,或者更改后能将visible信息一并更改
panoID: i,
//visibles: this.turnToPanoIndex(this.panoVTemp[i].seeMarkers),
visibles3: this.turnToPanoIndex(this.panoVTemp[i].neighbourUUIDs)
})
}
if (PanoData.length == 0) {
//没改变
alert("保存成功")
return;
}
/* this.afterSavePanoVisibles()
alert("保存成功")
console.log(JSON.stringify(PanoData)) */
let url = cmp ? ('/api/scene/roamViable/' + cmp) : '/manage/scene/roamViable'
$.ajax({
method: 'POST',
url: ceshi + url,
headers: {
'Content-Type': 'application/json',
token: token
},
contentType: 'application/json',
data: JSON.stringify({
data: JSON.stringify(PanoData),
sceneCode: window.number
}),
success: (data)=>{
if (data.code === 0) {
this.afterSavePanoVisibles()
alert("保存漫游可行成功")
} else
alert("保存漫游可行失败")
if (data.code === 5001) {
alert('请重新登录')
localStorage.dcj_token = ''
location.reload()
}
}
,
fail: function() {
alert("保存漫游可行失败")
}
})
/* var o = {
name_t: "panoVisible",
f: this.pauseSetPanoVisible,
url: Config.prefixEditProPCApi+"/saveLinkPano",
dialog: i18n.get('设置'),
data: { data: JSON.stringify(PanoData) }
}
var dataDeal = uploadsSaving.saveFucforPC(o);
dataDeal.group[0] = function () {
//实施:
for (var i in player.panoVTemp) {
var pano = player.model.panos.index[i];
pano.seeMarkers = player.panoVTemp[i].seeMarkers;
pano.neighbourUUIDs = player.panoVTemp[i].neighbourUUIDs;
pano.neighbourPanos = player.panoVTemp[i].neighbourPanos;
}
if(!player.model.checkHasNeighbor(player.currentPano)){//currentPano变为孤立点 就要换一个防止飞入
var list = player.model.panos.sortByScore([function(pano){return player.model.checkHasNeighbor(pano)}],
[function(pano){return -pano.position.distanceTo(player.currentPano.position)}])
if(list && list.length){
player.currentPano = list[0].pano;//找最近的一非孤立点
player.model.noPanoHasNeighbor = false; //更新状态
}else{
player.model.noPanoHasNeighbor = true; //更新状态
}
}else{
player.model.noPanoHasNeighbor = false; //更新状态
}
dataDeal.done();
player.model.updateFootIconSize(player.cameraControls.activeControl)//更新一下center大小 写在最后
} */
},
searchNeib: function(panoId) {
//寻找某pano的相关neighbour 可能是修改过的
var panos = player.model.panos;
var o = {};
if (this.panoVTemp[panoId]) {
//o.seeMarkers = this.panoVTemp[panoId].seeMarkers;
o.neighbourUUIDs = this.panoVTemp[panoId].neighbourUUIDs;
o.neighbourPanos = this.panoVTemp[panoId].neighbourPanos;
} else {
//o.seeMarkers = panos.index[panoId].seeMarkers.slice(0);
o.neighbourUUIDs = panos.index[panoId].neighbourUUIDs.slice(0);
o.neighbourPanos = CloneObject(panos.index[panoId].neighbourPanos);
}
return o;
},
turnToPanoIndex: function(panoArr) {
var panos = player.model.panos;
var array = [];
for (var i = 0; i < panoArr.length; i++) {
var pano = panos.index[panoArr[i]];
var index = panos.list.indexOf(pano)
array.push(index);
}
return array;
},
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;
},
delVisibleLines: function() {
//xzw add 所有线都删除
for (var i in this.tagsVLines) {
this.tagsVLines[i].geometry.dispose();
this.tagsVLines[i].material.dispose();
this.meshGroup.remove(this.tagsVLines[i]);
delete this.tagsVLines[i];
}
for (var i in this.panoVLines) {
this.panoVLines[i].geometry.dispose();
this.panoVLines[i].material.dispose();
this.meshGroup.remove(this.panoVLines[i]);
delete this.panoVLines[i];
}
},
//--------panoVisible
createPanoVisiLines: function(pano) {
// pano可见性线条
var neighbours = this.panoVTemp[pano.id] && this.panoVTemp[pano.id].neighbourPanos || pano.neighbourPanos;
for (var r in neighbours) {
if (neighbours[r] && r != pano.id) {
this.createPanoSingleLine(pano, "old", r)
}
}
},
createPanoSingleLine: function(pano, type, id) {
//pano是中心
var panos = player.model.panos;
var p2 = panos.index[id].floorPosition.clone()
/* .sub(player.model.position) */
var line = LineDraw.createLine([pano.floorPosition.clone()/* .sub(this.position) */
, p2], {
color: this.colors.green
});
this.meshGroup.add(line);
line.name = "PanoVL-" + type + "-" + id;
this.panoVLines[id] = line;
this.changeFIconState(panos.index[id].footIcon, "linked")
},
dealPanoVisible: function(id) {
//外部调用
var panos = player.model.panos;
if (this.panoVsetting) {
if (id == this.panoVsetting.id) {
//关闭当前pano设置
this.pauseSetPanoVisible('unsaved')
} else {
var link;
//结果是否连接
if (this.panoVLines[id]) {
this.panoVLines[id].visible = !this.panoVLines[id].visible;
link = this.panoVLines[id].visible;
this.changeFIconState(panos.index[id].footIcon, this.panoVLines[id].visible ? "linked" : false)
} else {
this.createPanoSingleLine(this.panoVsetting, "new", id)
link = true;
}
if (link) {
//如果连接上了,直接判断该点是可见的(有附近点),(不能通过checkHasNeighbor来判断,因为新增的线条可能不在它的neighbour中
this.changeFIconState2(panos.index[id].footIcon, true)
this.changeFIconState2(panos.index[this.panoVsetting.id].footIcon, true)
} else {
//否则需要checkHasNeighbor
this.changeFIconState2(panos.index[id].footIcon, this.checkHasNeighbor(panos.index[id]))
this.changeFIconState2(panos.index[this.panoVsetting.id].footIcon, this.checkHasNeighbor(this.panoVsetting))
}
/* if(window.routeArray){
if(this.panoVLines[id].visible)window.routeArray.push(id)
else{
let index = window.routeArray.indexOf(id)
index > -1 && routeArray.splice(index, 1)
}
} */
}
} else {
//点击开始设置要设置的pano
this.SetOnePanoVisible(panos.index[id])
}
this.updateFootIconSize()
},
showFootIcons: function(pano, isPanovisible) {
if (!this.footIcons) {
footTex1 = Texture.load("images/edit/End_128.png");
//Store.FootIcon);
footTex2 = Texture.load("images/edit/End_unable_128.png");
//Store.FootIcon_unable);
this.footIcons = [];
var scale = 0.4;
scale *= 40 / Math.sqrt(Math.min($("#player").width(), $("#player").height()));
//屏幕越小,放得越大
scale = THREE.Math.clamp(scale, 0.3, 0.7)
//console.log("scale"+scale)
var geo = new THREE.PlaneGeometry(scale,scale,1,1)
var panos = player.model.panos;
for (var r in panos.index) {
if (!panos.index[r].isAligned())
continue;
var t = THREE.UniformsUtils.clone(shaders.waypoint.uniforms);
t.map.value = footTex1
t.color.value.set("#ffffff");
var mat = new THREE.RawShaderMaterial({
vertexShader: shaders.waypoint.vertexShader,
fragmentShader: shaders.waypoint.fragmentShader,
uniforms: t,
side: THREE.DoubleSide,
transparent: !0,
depthWrite: !1,
depthTest: false,
name: "footIcon"
})
var foot = new THREE.Mesh(geo,mat)
foot.position.copy(panos.index[r].floorPosition.clone()/* .sub(player.model.position) */
)
foot.lookAt(foot.position.clone().add(new THREE.Vector3(0,1,0)));
foot.name = panos.index[r].id;
foot.visible = false;
foot.renderOrder = 6,
panos.index[r].footIcon = foot;
this.meshGroup.add(foot);
this.footIcons.push(foot)
}
}
for (var i = 0; i < this.footIcons.length; i++) {
this.footIcons[i].visible = true;
this.changeFIconState(this.footIcons[i], false)
var panos = player.model.panos;
if (isPanovisible) {
this.changeFIconState2(this.footIcons[i], this.checkHasNeighbor(panos.index[this.footIcons[i].name], "showFoot"))
}
if (pano && (this.footIcons[i].name == pano.id)) {
//pano为中心 或者 currentPano 所以放大一点
this.footIcons[i].oriScale = new THREE.Vector3(1.5,1.5,1.5)
if (isPanovisible) {
//currentPano特殊些:
this.changeFIconState(this.footIcons[i], "center")
//this.footIcons[i].Unclick = true;//不让点击和hover
}
} else {
this.footIcons[i].oriScale = new THREE.Vector3(1,1,1)
}
}
},
checkHasNeighbor: function(pano, state) {
//检查当前状态pano点是否有可通行点
var neighbours = /* this.panoVTemp && */
this.panoVTemp[pano.id] ? this.panoVTemp[pano.id].neighbourPanos : pano.neighbourPanos;
if (state != "showFoot" && pano == this.panoVsetting) {
//是中心点的话。state == "showFoot"代表是showFootIcon时, 这时候线还没创建,无法用线判断中心点有几个相邻点,直接用neighbourPanos
for (var i in this.panoVLines) {
if (this.panoVLines[i].visible) {
return true;
//有一条线即可
}
}
return;
}
for (var i in neighbours) {
if (i == pano.id)
continue;
if (neighbours[i]) {
if (this.panoVsetting && this.panoVsetting.id == i && this.panoVLines[pano.id] && !this.panoVLines[pano.id].visible)
continue;
return true;
}
}
return false;
},
/* ifAllPanoNoNeighbor : function(){//检查是否全是孤立点
var panos = player.model.panos;
for(var i in panos.index){
if(this.checkHasNeighbor(panos.index[i])){
return false;
}
}
this.noPanoHasNeighbor = true;
return true;//是全部没有neighbour
}, */
changeFIconState: function(footIcon, state) {
var color = state == "linked" ? this.colors.green : (state == "center" ? /* "#d7f244" */
"#d5f12e" : "#ffffff");
footIcon.material.uniforms.color.value.set(color)
},
changeFIconState2: function(footIcon, state) {
//是可见点还是不可见点
if (state) {
footIcon.material.uniforms.map.value = footTex1;
if (this.panoVsetting) {
if (this.panoVsetting.id != footIcon.name) {
footIcon.material.uniforms.opacity.value = 1;
} else {
this.changeVisiBtnState(true)
}
}
} else {
//不可见
footIcon.material.uniforms.map.value = footTex2;
if (!this.panoVsetting || this.panoVsetting.id != footIcon.name) {
//非中心点时
footIcon.material.uniforms.opacity.value = 0.5;
} else {
//变为中心点时
footIcon.material.uniforms.opacity.value = 1;
this.changeVisiBtnState(false)
}
}
},
hideFootIcons: function() {
if (!this.footIcons)
return;
for (var i = 0; i < this.footIcons.length; i++) {
this.footIcons[i].visible = false;
}
},
updateFootIconSize: function() {
//根据相机位置 改变footIcon大小,使在范围内看到的热点大小一致,防止太小点击不到
if (!this.footIcons)
return;
var s = player.cameraControls.controls.floorplan.absoluteScale * 2.8
s = THREE.Math.clamp(s, 0.5 * this.footIconSizeRatio, 1.4 * this.footIconSizeRatio);
this.footIcons.forEach(function(f) {
try {
f.scale.copy(f.oriScale).multiplyScalar(s);
} catch (e) {
console.log(e)
}
})
}
//========热点可见性==============
,
beginSetTagVisible: function() {
if (this.setTagVisible)
return;
$(".toolTop").addClass("unable")
$("#hotVisible").addClass("unable")
this.setTagVisible = true;
this.tagVTemp = {};
this.$confirmSnap.text('完成设置').removeClass("hide")
//objects.tagManager.hideAllTags();
for (let i in player.model.hots) {
player.model.hots[i]._isSprite = player.model.hots[i].isSprite;
player.model.hots[i].isSprite = true;
player.model.hots[i].mesh.material.depthTest = false;
}
this.setDisplay(true)
this.updateFootIconSize()
//更新一下大小,尤其是上次换了中心点然后退出又进入但是镜头没有变化的话
},
SetOneTagVisible: function(tag) {
//点击某个热点后就对该热点进行设置,或者在热点修改时对其进行设置
if (this.tagVsetting == tag)
return;
if (this.tagVsetting) {
this.saveLastTagVi(this.tagVsetting);
//this.tagVsetting.setElemType(this.tagVsetting.style, this.tagVsetting.styleImageURL);
}
this.tagVsetting = tag;
//记录正在修改的
this.delVisibleLines();
//删除线
this.showFootIcons(player.currentPano);
this.createTagVisiLines(tag);
//创线
this.updateFootIconSize()
//更新一下大小,尤其是上次换了中心点然后退出又进入但是镜头没有变化的话
},
saveLastTagVi: function() {
//保存刚设置过的tag
var change = false;
var newVPs = this.tagVTemp[this.tagVsetting.sid] || this.tagVsetting.visiblePanos.slice(0);
for (var r in this.tagsVLines) {
var line = this.tagsVLines[r];
if (line.name.indexOf("new") > -1 && line.visible) {
//新设置为visible且没有取消
newVPs.push(r)
change = true;
//console.log("add: "+r)
} else if (line.name.indexOf("new") == -1 && !line.visible) {
//旧的且已经取消
var i = newVPs.indexOf(r);
if (i == -1) {
console.log("visiblePanos删除error");
continue;
}
newVPs.splice(i, 1);
change = true;
//console.log("sub: "+r)
}
}
if (change) {
this.tagVTemp[this.tagVsetting.sid] = newVPs;
}
},
pauseSetTagVisible: function() {
//pc保存后删除连线 但还在继续设置 点选热点即开始
if (!this.setTagVisible || !this.tagVsetting)
return;
//this.tagVsetting.setElemType(this.tagVsetting.style, this.tagVsetting.styleImageURL );
this.delVisibleLines();
this.hideFootIcons();
this.tagVTemp = {};
this.tagVsetting = null;
},
finishSetTagVisible: function() {
if (!this.setTagVisible)
return;
$(".toolTop").removeClass("unable")
$("#hotVisible").removeClass("unable")
this.pauseSetTagVisible();
this.setTagVisible = false;
this.setDisplay(false)
this.$confirmSnap.addClass("hide")
permitTranMode(true)
/* for (var r in objects.tagManager.tags) {
if(objects.tagManager.tags[r].state == "videoPanoFlag")continue;
objects.tagManager.tags[r].disc.visible = false;
objects.tagManager.tags[r].disc.material.depthTest = true;
} */
for (let i in player.model.hots) {
player.model.hots[i].isSprite = player.model.hots[i]._isSprite;
player.model.hots[i].isSprite || player.model.hots[i].mesh.quaternion.copy(player.model.hots[i].quaternion)
player.model.hots[i].mesh.material.depthTest = true;
}
},
/* saveTagVisibles : function () { //保存到服务器
if (this.tagVsetting) this.saveLastTagVi(this.tagVsetting); //获取最后设置的那个热点的改动
//可能出现数据没变但保存的情况。比如先改变了然后切换别的热点但切换回来时又改回来。
var tags = [];
for (var i in this.tagVTemp) {
tags.push({
sid: i,
value: this.tagVTemp[i]//turnToPanoIndex(this.tagVTemp[i])
})
}
if (tags.length == 0) {//没有需要保存的改动
this.finishSetTagVisible()
return;
}
return tags;
} */
//afterSaveTagVisibles : function(){
saveTagVisibles: function() {
if (this.tagVsetting)
this.saveLastTagVi(this.tagVsetting);
for (var i in this.tagVTemp) {
//保持成功于是生效
player.model.hots[i].visiblePanos = this.tagVTemp[i];
}
this.finishSetTagVisible()
//还是保存完直接结束吧,因为现在热点可视不放在单独的设置页面了
},
createTagVisiLines: function(tag) {
// 热点可见性线条
var panos = player.model.panos;
tag.visiblePanos || tag.setVisiblePanos("get")
var visibleList = this.tagVTemp[tag.sid] || tag.visiblePanos;
//如果是刚在设置的要读取设置过的数据
for (var r = 0; r < visibleList.length; r++) {
var pano = panos.index[visibleList[r]];
this.createTagSingleLine(pano, "old", tag)
}
},
createTagSingleLine: function(pano, type, tag) {
var panos = player.model.panos;
var line = LineDraw.createLine([pano.floorPosition.clone()/* .sub(this.position) */
, tag.mesh.position.clone()], {
color: this.colors.green
});
this.meshGroup.add(line);
line.name = "tagVL-" + type + "-" + pano.id;
this.tagsVLines[pano.id] = line;
this.changeFIconState(panos.index[pano.id].footIcon, "linked")
},
dealTagVisible: function(tag, panoName) {
//外部调用
var panos = player.model.panos;
if (this.tagsVLines[panoName]) {
this.tagsVLines[panoName].visible = !this.tagsVLines[panoName].visible;
this.changeFIconState(panos.index[panoName].footIcon, this.tagsVLines[panoName].visible ? "linked" : false)
} else {
this.createTagSingleLine(panos.index[panoName], "new", tag)
}
},
delVisibleLines: function() {
//xzw add 所有线都删除
for (var i in this.tagsVLines) {
this.tagsVLines[i].geometry.dispose();
this.tagsVLines[i].material.dispose();
this.meshGroup.remove(this.tagsVLines[i]);
delete this.tagsVLines[i];
}
for (var i in this.panoVLines) {
this.panoVLines[i].geometry.dispose();
this.panoVLines[i].material.dispose();
this.meshGroup.remove(this.panoVLines[i]);
delete this.panoVLines[i];
}
}
}
function permitTranMode(state) {
state ? $(".pinBottom.left").removeClass('hide') : $(".pinBottom.left").addClass('hide');
}
function randomWord(randomFlag, min, max) {
//随机字符串
var str = ""
, range = min
, arr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
if (randomFlag) {
// 随机长度
range = Math.round(Math.random() * (max - min)) + min;
}
for (var i = 0; i < range; i++) {
var pos = Math.round(Math.random() * (arr.length - 1));
str += arr[pos];
}
return str;
}
function getRandomSid() {
//5-7位随机字符串 + 6位时间 为热点准备
var pre = randomWord(true, 5, 7);
var post = new Date().getTime() + "";
var len = post.length;
post = post.substring(len - 8, len - 5) + post.substring(len - 3, len)
//其实还是有可能重复的....
return pre + post;
}
function searchParent(searchArea, o, maxTimes) {
//是否是某种元素的下级,并找出该元素
maxTimes = maxTimes || 20;
var count = 0
var f = function(dom) {
if (o.id && o.id == dom.id)
return dom
else if (o.className && dom.classList && dom.classList.contains(o.className))
return dom
else if (o.tagName && dom.tagName && o.tagName.toUpperCase() == dom.tagName.toUpperCase())
return dom
}
var find;
while (searchArea && count < maxTimes) {
if (find = f(searchArea))
return find
searchArea = searchArea.parentNode;
count++;
}
}
class ListBox{//下拉列表
//elemArr:初始的列表,内含每项的dom.
constructor(elemArr, $rootDom, options={}){
this.listDom = $rootDom.find('ul.list')
this.listTitle = $rootDom.find('.selection')
this.chosenItem = null
this.options = options;
this.bindEvents()
elemArr.forEach(($dom, i)=>{
this.addItem($dom)
})
}
updateSelectDisplay(){
this.listDom.children().removeClass('selected')
this.chosenItem && this.chosenItem.addClass("selected")
this.options.selectFun(this.chosenIndex)
}
selectFromOutSide(index ){
this.chosenIndex = index;
this.chosenItem = index == void 0 ? null : this.listDom.children().eq(index)
this.updateSelectDisplay()
}
addItem($dom){
this.listDom.append($dom)
if(this.options.addFun){
this.options.addFun($dom)
}
$dom.on('click',()=>{
this.chosenItem = $dom;
this.chosenIndex = $dom.index();
this.updateSelectDisplay()
})
}
removeItem($dom){
$dom.remove()
if(this.options.delFun){
this.options.delFun($dom)
}
}
saveTemp(){//编辑热点时保存一份副本
this.temp = Array.from(this.listDom.children()).map((li)=>{
return li.outerHTML
})
this.options.saveTemp && this.options.saveTemp(this)
}
recover(){//取消编辑时恢复
this.listDom.html('')
this.temp.forEach(html=>{
this.addItem($(html));
})
this.options.recover && this.options.recover(this)
this.selectFromOutSide(this.chosenIndex)
}
bindEvents(){
this.listTitle.on('click',(e)=>{
e.stopPropagation()
this.listDom.toggleClass('hide')
})
document.addEventListener('click',()=>{
this.listDom.addClass('hide')
})
}
}