/* var ceshi = '';
// var ceshi = 'http://192.168.0.135:8105';
// var ceshi = 'http://47.107.252.54:8105';
// var token = "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGUiOm51bGwsIm1hbmFnZXIiOm51bGwsImlkIjoxLCJ1c2VyTmFtZSI6ImFkbWluIiwiZXhwIjoxNTk2NzAxNjAyLCJpYXQiOjE1OTY2MTUyMDIsImp0aSI6Ijk0YjA5YTg1LWViY2ItNDE1Yy04OGVmLWU0MDM1M2UzYmIxYyJ9.Uzi95n0kYXp7bdpY77MdLtTpPL_Fq-jn0tE7gjg6AzA"
var token = window.localStorage.dcj_token
*/
var confirmSnap = $(".confirmSnap.innerBtn");
var snapshotGui = $(".snapshotGui.overlayGui");
var _musicMaxWeight = 8
//M
var cmp = getQueryVariable('cmp') || ''
var _hotNum = 0
function reData(data, type) {
return JSON.stringify(data) == type ? null : data
}
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 += '.')//补小数点
}
//新编辑界面
var EditTools = function(n) {
//main2018 里面的主要对象
this.n = n;
//当前状态
this.atPanel = null;
//场景信息
this.sceneInformation = new SceneInformation();
//热点
this.hotpoint = new Hotpoint();
//导览
this.editGuide = new EditGuide();
//音乐
this.EditBGM = new EditBGM();
//初始化界面
//this.init();
this.data = {}
this.editLabel = new EditLabel();
}
EditTools.prototype.loadDone = function(name, data){
this.data[name] = data
if('data' in this.data && 'data2' in this.data){
this.init();
}
}
EditTools.prototype.init = function() {
this.hotpoint.init(/* this.n */);
var that = this;
this.initSaveAll();
this.active();
if(player.mode != 'panorama'){
$(".toolLeft li[data-name=panoVisible]").addClass('unable')
player.once("pano.chosen",()=>{
$(".toolLeft li[data-name=panoVisible]").removeClass('unable')
})
}
//创建导览
that.EditBGM.init(this.data.data);
that.sceneInformation.init(this.data.data, this.data.data2)
// fyz 初始化导览需要两部分数据, 其中data2为data.js中的数据
that.editGuide.init(this.data.data, this.data.data2);
that.editLabel.init()
$("body").on("click", function() {
$(".DelConfirm").removeClass("active");
})
player.on("mode.changing",(currentMode, mode, pano)=>{ //起飞
if(this.atPanel != "screen" && !editTool.hotpoint.gettingCameraData) return
if(currentMode == "panorama") confirmSnap.addClass("unable")
})
player.on("flying.ended",(/* toPos, fromPos, pano */)=>{ //飞结束
if(this.atPanel != "screen" && !editTool.hotpoint.gettingCameraData) return
if(player.mode == "panorama") confirmSnap.removeClass("unable")
})
/* $(" .MenuOptions li").on("click", (e)=>{
var $elem = $(e.target);
$elem.closest('.MenuOptions').find('li').removeClass("chosen");
$elem.addClass("chosen");
}) */
//fyz 拖拽以改变顺序
{
let tourListNode = $("#tourList>ul")[0];
let tourItemListNode = $("#tourItemList>ul")[0];
let callback = function(ul){
reIndexTourList(ul)
}
//导览拖拽
setDraggable({ul:tourListNode, dragItemClassName:['guideItem', 'listItem'], callback})
setDraggable({ul:tourItemListNode, dragItemClassName:['guideItem'], callback })
//热点媒体拖拽
setDraggable({ul:$('#hotpointDetail [name="video"] .list')[0], dragItemClassName:['mediaItem'] })
setDraggable({ul:$('#hotpointDetail [name="photo"] .list')[0], dragItemClassName:['mediaItem'] })
//热点列表拖拽
setDraggable({ul:$('.toolRight .spotList')[0], dragItemClassName:['listItem']})
//roomLabel列表拖拽
setDraggable({ul:$('.toolRight .roomLabels [name="list"]>ul')[0], dragItemClassName:['listItem']})
}
$(".toolRight .panoVisible [name=autoCompute]").on('click',()=>{
VisiSet.resetPanosVisiByModel()
})
//平面图方向固定
this.fpAngleOptions = new MenuOptions({
dom: $(".toolRight .information [data-name=floorPlanAngle] .MenuOptions"),
uiCallBack : (o)=>{
var name = o.name == void 0 ? o.$li.attr('index') : o.name
_settings.floorPlanAngle = parseFloat(name) * Math.PI/2 //设置好方向 (0是无效的,将不设置)
if(name != 0){
if(player.mode != 'floorplan' && player.modeTran.split('-')!= 'floorplan'){
player.flyToMode('floorplan')
}else{
player.flyToMode('floorplan',()=>{
player.cameraControls.controls.floorplan.rotateToAngle(_settings.floorPlanAngle)
})
}
}
},
callbackWhenChose:(o)=>{
var name = o.$li.attr('index')
}
})
this.fpAngleOptions.updateChoseAtUI({name: Math.round(_settings.floorPlanAngle/(Math.PI/2))})
}
//点击的时候激活状态
EditTools.prototype.active = function() {
var that = this;
$('.toolBottom .toolLeft li').click(function() {
var name = $(this).data("name");
$('.toolLeft li[data-name=' + name + ']').addClass("active").siblings().removeClass("active");
$('.toolRight .' + name).removeClass("hide").siblings().addClass("hide");
if (name == that.atPanel)
return;
console.log(`atPanel ${that.atPanel} name ${name}`)
switch (that.atPanel) {
//退出
case "panoVisible":
VisiSet.finishSetPanoVisible()
break;
case "panoLog":
VisiSet.finishSetPanoLog()
break;
case "screen":
confirmSnap.addClass("hide").removeClass("unable");
snapshotGui.hide();
break;
/* case "overlay":
EditOverlay.leave()
break; */
case "hotpoint":
$("#hotpointDetail").hasClass("atRight") || $("#hotpointDetail a.close").click();
VisiSet.finishSetTagVisible()
that.hotpoint.wireframeModel.visible = false
break;
case 'roomLabels':
that.editLabel.leave()
break;
}
switch (name) {
case "hotpoint":
that.hotpoint.wireframeModel.visible = that.hotpoint.wireframeModel.shouldShow
break;
case "panoVisible":
$(".toolLeft").addClass("unable")
VisiSet.enterSet(VisiSet.beginSetPanoVisible.bind(VisiSet))
break;
case "panoLog":
$(".toolLeft").addClass("unable")
VisiSet.enterSet(VisiSet.beginSetPanoLog.bind(VisiSet))
break;
case "screen":
confirmSnap.removeClass("hide");
$('#camera-start').text("点此设置为初始画面")
snapshotGui.show();
if (player.mode != "panorama")
confirmSnap.addClass("unable")
break;
/* case "overlay":
EditOverlay.enter()
break; */
case 'snapTour':
that.editGuide.scroller.tourBlackSpeed.InitOffset()
that.editGuide.scroller.tourWalkSpeed.InitOffset()
break;
case 'roomLabels':
that.editLabel.enter()
break;
}
that.atPanel = name;
/* if(name != "hotpoint"){
$("#hotpointDetail").hasClass("atRight") || $("#hotpointDetail a.close").click()
} */
})
//滚动阻止事件
$(".toolRight div.content").on("mousewheel", function(event) {
event.stopPropagation()
});
// 输入框阻止事件
$('.toolRight').on('keydown', function(ev) {
ev.stopPropagation();
})
//加空格和回车字符
$(".buttons[name='addSign'] button").on('click',function(e){
let forAttr = $(this).parent().attr('for')
let textarea = forAttr ? $('#'+forAttr) : $(this).parent().parent().find('textarea')
let sign = $(this).attr('name') == 'space' ? ' ' : '
'
var v = textarea.val();
textarea.val(v + sign)
})
}
//保存按钮
EditTools.prototype.initSaveAll = function() {
var that = this;
$('#save').on('click', function() {
$(".edit-loading").removeClass("hide");
var $shareImages = $(".information .edit-fun-images a.result");
new Promise(function(resolve, reject) {//分享图
upload($shareImages, 'images', resolve)
}).then(function(imgUrls) {
//导览的数据
var guides = that.editGuide.getSavingInfo()/* Array.from($('.tourFolderList ul li')).map(function(dom) {
return dom.data
}) */
let tourRotTime = parseFloat($('.toolRight .snapTour [name="rotTime"] input').val())
isNaN(tourRotTime) && (tourRotTime = '')
var info = {
name: $('#pjtName').val(),
summary: $('#info-summary').val(),
weixinDesc: $('#weixin-summary').val(),
shareImgUrl: imgUrls[0] || '',
backgroundMusic: that.EditBGM.musicBox.getSrc() || '',
bgName: that.EditBGM.musicBox.getName(),
hoticon: JSON.parse($(".hotStyle-item li.active").attr("data-val")),
camera_start: $(".screen .shotImg.innerBtn")[0].cameraData,
loadlogo: $("#loadlogo").is(':checked'),
special: $("#g_specialScene").is(':checked'),
vision_version: $("#twoData").is(':checked') ? "1.1.562.17209" : false,
roomLabels: that.editLabel.getSavingInfo(),
/************************************** 方奕卓 场景可配置项 ******************************************/
hotImageScale: $("#hotImgScale").is(':checked'),
// 热点图片可放大
autoAdjustHotScale : $("#autoAdjustHotScale").is(':checked'),
hideFloorMarker: $("#hideFloorMarker").is(':checked'),
// 地面标记
hideMouseMarker: $("#hideMouseMarker").is(':checked'),
showingLabels: $("#showingLabels").is(':checked'),
// 鼠标标记
floorMarkerColor: $('#floorMarkerColor').val(),
// 地面/导览标志颜色
mouseMarkerColor: $('#mouseMarkerColor').val(),
// 鼠标标志颜色
momentTour: $('#tourSwitch input').is(':checked') ? 'black' : 'walk',
tourBlackSpeed : that.editGuide.scroller.tourBlackSpeed.value,
tourWalkSpeed : that.editGuide.scroller.tourWalkSpeed.value,
tourRotTime,
momentTourBlackNewType : $('#newBlack').is(':checked'),
showHotListSta: $('#hotListSwitch').is(':checked'),
// 开启热点列表
//hotIconScale: DATA.hotIconScale,
// 热点缩放
supportsVR: $('#VRSwitch input').is(':checked'),
// 开启VR功能
/**************** 陈志广 小地图可配置项 *********** */
cadSignColor: $('#cadSignColor').val(),
cadBorderColor: $('#cadBorderColor').val(),
cadBorderWidth: $('#cad-size').val(),
showCad: $('input[name="show-cad"]').is(':checked'),
/**********/
floorPlanAngle: _settings.floorPlanAngle || 0 //俯视图旋转角
}
var data = {
sceneCode: number,
hots: reData(that.hotpoint.getSavingInfo(), '{}'),
//tourAudio: reData(that.editGuide.tourAudio,'{}'),//for 旧版
name: number,
guides: reData(guides, '[]'),
info: info,
}
console.log(data)
let url = cmp ? ('/api/scene/edit/' + cmp) : '/manage/scene/edit'
$.ajax({
method: 'POST',
headers: {
'Content-Type': 'application/json',
token: token
},
dataType: 'json',
contentType: 'application/json',
url: ceshi + url,
data: JSON.stringify(data),
success: function(data) {
if (data.code === 0) {//成功
//manage.showInfo("保存成功")
location.reload()
}else if (data.code === 5001) {
alert('请重新登录')
localStorage.dcj_token = ''
location.reload()
}else{
alert(`saveAll (url:${url}) code : ${data.code} \n${data.msg}`)
}
}
})
});
})
}
class EditLabel{
constructor(){
}
init(){
let reverse = player.model.roomLabels.slice(0).reverse()
reverse.forEach(e=>this.addLebelCallback(e))
$('.toolRight .roomLabels .addBtn button').on('click',()=>{//准备添加
if(this.editingLabel){
this.setEditLabel(false, this.editingLabel)
}
this.setAddState(true)
})
$('.toolRight .roomLabels [name="title"] input').on('input',(e)=>{//标题
this.editingLabel.setTitle(e.target.value)
this.editingLabel.$li.find('.title').text(e.target.value)
})
/* $('.toolRight .roomLabels [name="delete"] button').on('click',(e)=>{//删除
this.deleteLabel(this.editingLabel)
this.setEditLabel(false,this.editingLabel)
}) */
player.on('getIntersect',(intersect, consume)=>{//添加
if(this.adding){
var position = intersect.point.clone();
position.y += 0.5
//var floorIndex = player.model.allFloorsVisible ? null : player.model.currentFloor.floorIndex
var floorIndex = intersect.object.parent.parent.floorIndex
var label = new RoomLabel({position, title:'' , floorIndex })
player.model.roomLabels.push(label)
this.setAddState(false)
this.addLebelCallback(label)
this.setEditLabel(true, label) //开始编辑
this.adding = false
label.update()
consume(true)
}
})
//点击列表弹出按钮
$('.toolRight .roomLabels [name="list"]>ul').on("click", (e)=>{
var target = $(e.target);
let li = searchParent(e.target, { className: 'listItem' }, 7);
if(!li)return;
let label = li.label
if (target.hasClass("del")) {
e.stopPropagation();
target.siblings(".DelConfirm").addClass("active");
} else {
if (target.hasClass("DelConfirm")) {
e.stopPropagation();
this.deleteLabel(label);
}else{
this.setEditLabel(true, label) //开始编辑
}
}
});
}
deleteLabel(label){
let index = player.model.roomLabels.indexOf(label)
index > -1 && player.model.roomLabels.splice(index,1)
label.dispose()
label.$li.remove()
if(this.editingLabel == label){
this.setEditLabel(false,this.editingLabel)
}
}
addLebelCallback(label){
this.addLebelEvent(label)
this.addToList(label)
}
addToList(label){
var $li = $("
" + label.title + "
确定删除
");
$li[0].label = label
label.$li = $li;
$('.toolRight .roomLabels [name="list"]>ul').prepend($li)
}
setAddState(state){
state ? CursorDeal.add('addLabel') : CursorDeal.remove('addLabel')
this.adding = state
}
setEditLabel(state, label){
let pannel = $('.toolRight .roomLabels li[name="prop"]')
if(state){
if(this.editingLabel){
this.setEditLabel(false, this.editingLabel)
}
label.elem.addClass('selected')
pannel.removeClass('hide')
pannel.find('[name="title"] input').val(label.title)
label.setEditSelect(true)
pannel.insertAfter(label.$li)
this.editingLabel = label
}else{
label.elem.removeClass('selected')
pannel.addClass('hide')
label.setEditSelect(false)
this.editingLabel = null
}
}
addLebelEvent(label){
//拖拽
let dragElemShift = {}
let dragging = false
const startDrag = (evt) => {
if(!this.editing )return
dragging = true
$('#player').on("mousemove", drag);
label.elem.find('a').css('pointer-events','none')
/* if(player.mode != 'floorplan'){ //换算到elem的底部
let lebelWidth = label.elem.children(0).width()
let lebelHeight = label.elem.children(0).height() * (68+24) / 24 ;//
dragElemShift = {x: -evt.offsetX + lebelWidth/2, y: 100 } //y向不准确,因为原本添加时提高了0.5,而0.5对应的像素需要根据视角,那就算了吧
}else{
dragElemShift = {x:0,y:0}
} */
CursorDeal.add('moveLabel')
};
const endDrag = (evt) => {
dragging = false
$('#player').off("mousemove", drag);
label.elem.find('a').css('pointer-events','')
CursorDeal.remove('moveLabel')
};
const drag = (evt) => {
if (dragging) {
evt.preventDefault();
let mouse = new THREE.Vector3()
let meshes = player.model.allFloorsVisible ? player.model.colliders : player.model.currentFloor.collider.children
math.convertScreenPositionToNDC(evt.offsetX/* +dragElemShift.x */, evt.offsetY/* +dragElemShift.y */, mouse);
var intersect = convertTool.getMouseIntersect(player.camera, meshes, mouse)
if(intersect){
let position = intersect.point.clone()
position.y += 0.5
label.setPos(position)
var floorIndex = intersect.object.parent.parent.floorIndex
label.floorIndex = floorIndex
}
//this.dispatchEvent({type:'dragged', position: this.position})
}
};
label.elem.on('mousedown', startDrag);
$(document).on('mouseup', endDrag);
$("#player").on('mouseup', endDrag);
//点击编辑:
label.elem.on('click',(e)=>{
if(this.editing){
this.setEditLabel(true,label)
}
e.stopPropagation()
})
}
enter(){
this.editing = true
player.roomLebelClickUnabled = true
}
leave(){
this.editing = false
this.editingLabel && this.setEditLabel(false, this.editingLabel)
player.roomLebelClickUnabled = false
this.setAddState(false)
}
getSavingInfo(){
var info = Array.from($('.toolRight .roomLabels [name="list"] .listItem')).map((li,index)=>{
let label = li.label
return {
//order: index,
title : label.title,
position : toPrecision(label.position.toArray(), 4),
floorIndex: label.floorIndex
}
})
console.log(info)
return info
}
}
//场景信息编辑
var SceneInformation = function() {}
SceneInformation.prototype.init = function(data, data2) {
var $options = $('.hotStyle-item li');
var $loadlogo = $("#loadlogo");
var $hotImageScale = $("#hotImgScale");
var $hideFloorMarker = $("#hideFloorMarker");
var $hideMouseMarker = $("#hideMouseMarker");
var $showingLabels = $("#showingLabels");
var $g_specialScene = $("#g_specialScene");
var $twoData = $("#twoData");
/*******************方奕卓 其他项需要用到data来初始化, 故一并放到这里 ******************/
let momentTour = $('#tourSwitch input');
// 导览瞬间过渡开关
let hotListSwitch = $('#hotListSwitch');
// 热点图标缩放
let VRSwitch = $('#VRSwitch input');
// VR功能开启
/***********************************************************************************/
$(".model-title2").text(data.name);
$('#pjtName').val(data.name);
$('#info-summary').val(data.summary);
//if (data2) $('#weixin-summary').val(data2.weixinDesc);
$('#weixin-summary').val(data.weixinDesc);
for (var i = 0; i < $options.length; i++) {
if ($options.eq(i).attr('data-val') === JSON.stringify(data.hoticon)) {
$options.eq(i).addClass("active").siblings().removeClass("active");
}
}
$(".screen .shotImg.innerBtn")[0].cameraData = data.camera_start;
$(".shotImg.innerBtn").on("click", function(){
var EntryInfo = this.cameraData
if (EntryInfo) {
var to = player.model.panos.get(EntryInfo.pano.uuid);
var q = new THREE.Quaternion().fromArray(EntryInfo.camera.quaternion);
var lookAtPoint = new THREE.Vector3(0,0,-1).applyQuaternion(q).add(to.position);
player.flyToPano({
pano: to,
lookAtPoint: lookAtPoint
})
}
}
)
if(data.shareImgUrl){
var imagesHTML = ''
$(".information .edit-fun-images.list ").html(imagesHTML);
$("#shareImgUpload").addClass("hide")
}
if(data.spotImgUrl){
}
/*************方奕卓 其他项的初始化操作 ************/
initColorElem(data);
// 给其他元素绑定事件
if (data.momentTour === 'black') {
momentTour.prop('checked', true);
}
if (data.showHotListSta) {
hotListSwitch.prop('checked', true);
}
if (data.momentTourBlackNewType) {
$('#newBlack').prop('checked', true);
}
/* if (data.hotIconScale) {
$('#hotIconScale input').val(parseFloat(data.hotIconScale));
} */
/* $('#hotIconScale_2 input').on('change',(e)=>{
var s = THREE.Math.clamp(parseFloat(e.target.value), 0.1, 100)
e.target.value = s
editTool.hotpoint.editSpot.mesh.scale.set(s,s,s)
}) */
if (data.supportsVR) {
VRSwitch.prop('checked', true);
}
/************************************************/
//隐藏公司logo
if (data.loadlogo) {
$loadlogo[0].checked = true
showLogo();
}
// 热点图片放大
if (data.hotImageScale) {
$hotImageScale[0].checked = true
}
// 隐藏地面标记
if (data.hideFloorMarker) {
$hideFloorMarker[0].checked = true
}
// 隐藏鼠标标记
if (data.hideMouseMarker) {
$hideMouseMarker[0].checked = true
}
if (data.showingLabels) {
$showingLabels[0].checked = true
}
//特殊大场景
if (data.special) {
$g_specialScene[0].checked = true
}
//启动二代的数据
if (data.vision_version === "1.1.562.17209" || data.vision_version) {
$twoData[0].checked = true
}
}
/**
* 初始化颜色选择的html元素
* @param {*} data
* @param {*} elem
*/
function initColorElem(data, elem) {
let $floorMarkerColor = $('#floorMarkerColor');
let $mouseMarkerColor = $('#mouseMarkerColor');
let $floorMarkerColorTex = $('#floorMarkerColorTex');
let $mouseMarkerColorTex = $('#mouseMarkerColorTex');
let $cadSignColor = $('#cadSignColor');
let $cadSignColorTex = $('#cadSignColorTex');
let $cadBorderColor = $('#cadBorderColor');
let $cadBorderColorTex = $('#cadBorderColorTex');
var colorRe = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/;
// 事件监听
$floorMarkerColor.on('change', function(e) {
$('#floorMarkerColorTex').val(e.target.value)
})
$floorMarkerColorTex.on('blur keydown', function(e) {
(e.type === 'blur' || e.type === 'keydown' && e.keyCode === 13) && setColor(e, $floorMarkerColor, this);
})
$mouseMarkerColor.on('change', function(e) {
$('#mouseMarkerColorTex').val(e.target.value)
})
$mouseMarkerColorTex.on('blur keydown', function(e) {
(e.type === 'blur' || e.type === 'keydown' && e.keyCode === 13) && setColor(e, $mouseMarkerColor, this);
})
// 事件监听
$cadSignColor.on('change', function(e) {
$('#cadSignColorTex').val( e.target.value)
})
$cadSignColorTex.on('blur keydown', function(e) {
(e.type === 'blur' || e.type === 'keydown' && e.keyCode === 13) && setColor(e, $cadSignColor, this);
})
// 事件监听
$cadBorderColor.on('change', function(e) {
$('#cadBorderColorTex').val( e.target.value)
})
$cadBorderColorTex.on('blur keydown', function(e) {
(e.type === 'blur' || e.type === 'keydown' && e.keyCode === 13) && setColor(e, $cadBorderColor, this);
})
// 设置颜色值
function setColor(e, colorElem, inputElem) {
var isColor = colorRe.test(e.target.value);
isColor && colorElem.val(e.target.value);
// isColor ? colorElem.val(e.target.value): (inputElem.placeholder = colorElem.val());
}
// 判断data中是否有存在的颜色值, 否则设置默认值
data.floorMarkerColor ? $floorMarkerColor.val(data.floorMarkerColor) : $floorMarkerColor.val('#4bcdfc');
data.mouseMarkerColor ? $mouseMarkerColor.val(data.mouseMarkerColor) : $mouseMarkerColor.val('#4bcdfc');
// 判断data中是否有存在的颜色值, 否则设置默认值
data.cadSignColor ? $cadSignColor.val(data.cadSignColor) : $cadSignColor.val('#00c8af');
data.cadBorderColor ? $cadBorderColor.val(data.cadBorderColor) : $cadBorderColor.val('#ffffff');
$('input[name="show-cad"]')[0].checked = !!data.showCad
$('#cad-size > option[value="'+(data.cadBorderWidth ? data.cadBorderWidth : '0.01')+'"]').attr("selected",true);
if (data.showCad) {
$('input[name="show-cad"]').trigger('change')
}
$('#panoIdColor').on('change', function(e) {
$('#panoIdColorTex').val(e.target.value)
VisiSet.changePanoIdColor(e.target.value)
})
$('#panoIdColorTex').on('blur keydown', function(e) {
(e.type === 'blur' || e.type === 'keydown' && e.keyCode === 13) && setColor(e, $('#panoIdColor'), this);
VisiSet.changePanoIdColor(e.target.value)
})
$('#panoIdColor').val('#c13e3e')//初始颜色
$('#panoIdColorTex').val('#c13e3e')
}
$('input[name="show-cad"]').on('change', function(ev) {
if (!ev.target.checked) {
return $('.cad').hide()
}
let taht = this
if (!taht.floorJSON) {
$.ajax({
url: '//super.4dage.com/data/'+ window.number +'/floor.json',
method: 'GET',
success(res) {
taht.floorJSON = res
loadCAD(taht.floorJSON)
$('#cadSignColor').on('change', function(ev) {
loadCAD()
})
$('#cadBorderColor').on('change', function(ev) {
loadCAD()
})
$('#cad-size').on('change', function(ev) {
loadCAD()
})
},
error() {
alert('当前场景没有小地图floor.json文件,请联系三维部门添加')
ev.target.checked = false
}
})
} else {
console.log('0000000000000000000')
$('.cad').show()
}
})
function loadCAD(data) {
grendCAD(data, $('#player')[0], $('#cadSignColor').val(), $('#cadBorderColor').val(), $('#cad-size').val())
}
//设置初始界面
function getSeft(seft) {
$('#camera-start').on('click', function(e) {
if (VisiSet.setPanoVisible) {
return VisiSet.savePanoVisibles()
} else if (VisiSet.setTagVisible) {
return VisiSet.saveTagVisibles()
}
var snapType = editTool.hotpoint.editSpot ? 'hot' : 'screen'
var preview = snapType == 'screen' ? $(".screen .shotImg.innerBtn")[0] : $('#hotpointDetail .shotImg.innerBtn')[0]
var snap = JSON.parse("{" + seft.getSnapAngleInfo() + "}")
preview.cameraData = {
camera: {
position: snap.metadata.camera_position,
quaternion: snap.metadata.camera_quaternion// 相机朝向
},
pano: {
uuid: snap.metadata.scan_id // 起始点位的id
}
}
var ev = document.createEvent("MouseEvent");//截取视图
g_snapShotWidth = snapType == 'screen' ? 240 * 4 : 240;
g_snapShotHeight = snapType == 'screen' ? 118 * 4 : 118;
//window.screenSta = 'startScreen';
ev.initMouseEvent("snapshotBegin", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
ev.__callback = (imgData,info)=>{
uploadImg(imgData, (rs)=>{
if (rs.code === 0) {
preview.cameraData.thumbImg = rs.data;
preview.style['background-image'] = "url(" + rs.data + ")"
}
}
, "thumbImg.jpg")
}
window.dispatchEvent(ev);
});
}
//热点编辑
var Hotpoint = function() {
this.spotList = $(".spotList");
this.hotpointDetail = $("#hotpointDetail");
this._scale = {}
this.scroller = {}
this.scroller.boxDepth = new SlideBar({
root: $('#boxDepth').eq(0),
value: 0,
min: 0 * 100,
max: 1 * 100,
name: "boxDepth",
unitStr: "cm",
avoidCrash: true,
onchange: (s)=>{
if (s == 0) {
this.editSpot.addBox(false)
} else {
this.editSpot.addBox(true)
this.editSpot.scale.z = s / 100 ;
this.updateTransform("scale")
}
},
dragEndEvent: function() {
}
})
// fyz 导览编辑页面同样采取热点编辑的样式, 这里确保只查找到热点编辑
}
Hotpoint.prototype.init = function() {
var that = this;
$(".hotStyle-item li").on('click', function() {//默认样式
$(this).addClass('active').siblings().removeClass('active');
})
// 添加多媒体
this.musicBox = musicPlayBoxBind(this.hotpointDetail.find("[name=audio].mediaUpload"), null )
this.addmediaInit();
// 添加音乐
this.addModel();
// 添加模型
this.addwebPack();
// 添加外链
this.wireframeModel = new THREE.Object3D;
if(Hot.allPhotoLoaded && Hot.allModelLoaded) this.initListSelect()
else Hot.whenAllFileLoaded = this.initListSelect.bind(this) //等全部photo加载完
player.model.hotGroup.children.forEach(e=>this.addHotList(e) )//创建列表
this.hotpointDetail.find(".tail .submit").on('click', this.saveHot.bind(this))
this.hotpointDetail.find("[name=info] input").on('change',(e)=>{//标题
this.editSpot.info.title = e.target.value
this.editSpot.setTitleElem()
})
//图片简介
{
let textarea = this.hotpointDetail.find('li[name="photo"] textarea');
textarea.on('change',(e)=>{
if(!textarea[0].currentBtn)return
textarea[0].currentBtn.desc = e.target.value;
this.imgDescBtnUpdate(textarea[0].currentBtn )
})
//应用到所有
this.hotpointDetail.find('li[name="photo"] button').on('click',()=>{
var choice = confirm("确定将文字应用到此热点的所有图片吗?");
if (choice) {
Array.from(that.hotpointDetail.find("[name=photo] .list .descBtn")).forEach(btn=>{
btn.desc = textarea[0].value
this.imgDescBtnUpdate(btn)
})
}
})
}
/* {
let ui = $('#hotIconScale input')
let min = parseFloat(ui.attr('min'));
let max = parseFloat(ui.attr('max'));
ui.on("change", function(e) {
var s = THREE.Math.clamp(parseFloat(e.target.value), min, max)
if(isNaN(s))s = 1
e.target.value = s
DATA.hotIconScale = s
})
} */
$(".hotpoint [name='adjustSize'] button").on('click',(e)=>{
let type = $(e.target).attr('index')
var c = 1.1
if(type == '-'){
s = 1/c
}else{
s = c
}
player.model.hotGroup.children.forEach(hot=>{
if(hot.texType == 'shine'){
hot.info.scale.multiplyScalar(s)
hot.scale.multiplyScalar(s)
}
})
DATA.hotIconScale *= s
})
this.isSpriteCheckBox = new CheckBox({dom: $("#isSprite"),
uiCallBack : (checked)=>{
},
callbackWhenChose:(checked)=>{
that.editSpot.info.isSprite = checked;
if(checked) {
that.editSpot.update(player)
}else{
that.editSpot.rotation.copy(that.editSpot.info.rotation)
}
}
})
//clickEvent
this.actionCheckBox = new CheckBox({dom: this.hotpointDetail.find("li[name='clickEvent'] li.editCheckbox input"),
uiCallBack : (checked, name)=>{
if(name == 'openHot'){
var content = that.hotpointDetail.find("li[name='content']")
checked ? content.removeClass('hide') : content.addClass('hide')
}else if(name == 'fastTran'){//瞬间过渡
var fastTran = that.hotpointDetail.find("li[name='fastTran']")
checked ? fastTran.removeClass('hide') : fastTran.addClass('hide')
}
},
callbackWhenChose:(checked, name)=>{
that.editSpot.info.actionType[name] = !!checked;
}
})
this.imgDescCheckBox = new CheckBox({dom: this.hotpointDetail.find("#addImgDesc"),
uiCallBack : (checked, name)=>{
var textarea = this.hotpointDetail.find('li[name="photo"] textarea');
var title = this.hotpointDetail.find('li[name="photo"] [name="descTitle"]')
if(!checked){
textarea.addClass('hide'), title.addClass('hide')
/* textarea.val('');
textarea[0].currentBtn = null */
}else{
textarea.removeClass('hide'), title.removeClass('hide')
}
var imgArea = this.hotpointDetail.find('li[name="photo"] .edit-fun-images');
checked ? imgArea.addClass('hasDescBtn') : imgArea.removeClass('hasDescBtn')
},
callbackWhenChose:(checked, name)=>{
that.editSpot.info.useImgDesc = !!checked;
}
})
//点击添加热点按钮
$('.hotpoint .addBtn button').on("click", function(e) {
g_HotStatus = $(e.target).attr('data-type');
//$("#player").css("cursor", "cell");
CursorDeal.add('addHot' )
});
//点击热点列表弹出按钮
this.spotList.on("click", function(e) {
var target = $(e.target);
let li = searchParent(e.target, { className: 'listItem' }, 7);
if(!li)return;
var hotId = $(li).attr("data-spid");
var hot = player.model.hots[hotId]
if(VisiSet.setTagVisible){
return VisiSet.SetOneTagVisible(hot)
}
if (target.hasClass("del")) {
e.stopPropagation();
target.siblings(".DelConfirm").addClass("active");
that.spotList.find("i").text(that.spotList.find("ul li").length);
} else {
if (target.hasClass("DelConfirm")) {
e.stopPropagation();
that.removeHot(hot);
} else {
//点击热点列表弹出编辑热点窗口
that.editHot(hot, $(li))
}
}
});
//关闭、取消
this.hotpointDetail.find(".head a.close, .tail button.cancel").on("click", ()=>{
var hot = this.editSpot
if(hot.isNew){
this.removeHot(hot)
}else{
this.recoverInfo(hot)
hot.updateVisible([player.currentPano])
}
this.tempInfos && player.model.hotGroup.children.forEach(hot=>{//还原所有同时修改了的贴图和模型
var info = this.tempInfos[hot.sid]
if(hot.texType == 'shine'){
hot.changeTexType(hot.texType, info.styleImg )
hot.info.styleImg = info.styleImg.map(e=>e.src)
}else{
hot.changeTexType(hot.texType, info.texMedia )
hot.info.texSrc = info.texMedia.src;
if(hot.texType == 'photo' && hot.info.animateInfo){
GifTexDeal.remove(hot.animation)
hot.animation = GifTexDeal.addAnimation(hot.material_.map, hot, hot.info.animateInfo )
GifTexDeal.start(hot.animation)
}
}
if(hot.objObject != info.objObject){
this.switchModel({add:info.objObject, spot:hot})
hot.info.scale.copy(info.scale)
hot.scale.copy(info.scale)
}
})
if(this.texLists){
for(let i in this.texLists){this.texLists[i].recover()}
this.modelList.recover()
}
this.editDone();
});
this.linkTypeMenuOptions = new MenuOptions({ //链接打开方式切换
dom: this.hotpointDetail.find(" .MenuOptions[name=linkType] "),
uiCallBack : (o)=>{
},
callbackWhenChose:(o)=>{
this.editSpot.info.linkType = o.$li.attr("index")
}
})
this.panoTransformCheckBox = new CheckBox({dom: $('#setPosForPano input') ,
uiCallBack : (checked, name)=>{
},
callbackWhenChose:(checked, name)=>{
if(!checked){
delete this.editSpot.info.transformAtPanos[getTransformSid()]
this.editSpot.position.copy(this.editSpot.info.position)
//this.editSpot.quaternion.copy(this.editSpot.quaternion)
}else{
this.getTransformAtPano('position')
}
}
})
/* $('#setPosForPano input').on("change", ()=>{
var on = $('#setPosForPano input').is(':checked')
if(!on){
delete this.editSpot.info.transformAtPanos[getTransformSid()]
this.editSpot.position.copy(this.editSpot.info.position)
//this.editSpot.quaternion.copy(this.editSpot.quaternion)
}else{
this.getTransformAtPano('position')
}
}) */
//是否显示模型线框
this.wireframeModel = new THREE.Object3D;
$('#wireframeSwitch input').on('change',(e)=>{
var visi = e.target.checked;
if(visi && this.wireframeModel.children.length == 0){
var mat = new THREE.MeshBasicMaterial({
wireframe: true,
opacity: 0.5,
color: "#57e4f3",
transparent: true
})
this.wireframeModel.name = 'wireframeModel'
player.model.chunks.forEach((mesh)=>{
var chunk = mesh.clone();
chunk.material = mat;
this.wireframeModel.add(chunk)
})
this.wireframeModel.visible = false
player.model.add(this.wireframeModel)
}
this.wireframeModel.visible = visi
this.wireframeModel.shouldShow = visi
})
$("#autoAdjustHotScale")[0].checked = !!DATA.autoAdjustHotScale;
//动画
this.gifCheckBox = new CheckBox({dom: $("#gifSwitch input"),
uiCallBack : (checked )=>{
$("#gifInfoEdit").css({display: checked ? 'block' : 'none'})
},
callbackWhenChose:(checked )=>{
if(checked){
that.editSpot.info.animateInfo = {
cellXcount : parseInt($("#gifXCount").val()),
cellYcount : parseInt($("#gifYCount").val()),
voidCount : parseInt($("#voidCount").val()),
loop : true,
duration : parseFloat($("#gifDuration").val()) * 1000
}
that.editSpot.animation = GifTexDeal.addAnimation(that.editSpot.material_.map, that.editSpot, this.editSpot.info.animateInfo, this.editSpot.sid)
GifTexDeal.start(that.editSpot.animation)
}else{
GifTexDeal.remove(that.editSpot.animation)
that.editSpot.info.animateInfo = null
}
}
})
{//gif动画 input
let changeAnimation = function(){
GifTexDeal.setRepeart(that.editSpot.animation.animation)
that.useSuitableRatio()
}
let restartAnimation = function(){
GifTexDeal.stop(that.editSpot.animation)
GifTexDeal.start(that.editSpot.animation)
}
let changeFrameCount = function(){
var a = that.editSpot.info.animateInfo
var frameCount = a.cellXcount * a.cellYcount - (a.voidCount||0)
$("#gifFrameCount").text(frameCount)
var fps = parseFloat($("#gifFps").val())
a.duration = frameCount / fps * 1000
$("#gifDuration").val(toPrecision(a.duration/1000, 2))
}
let gifXCountFun = function(value){
that.editSpot.info.animateInfo.cellXcount = value
var gifImgWidth = parseFloat($("#gifImgWidth").text())
var gifCellWidth = toPrecision(gifImgWidth / that.editSpot.info.animateInfo.cellXcount,1);
$("#gifCellWidth").text(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){
that.editSpot.info.animateInfo.cellYcount = value
var gifImgHeight = parseFloat($("#gifImgHeight").text())
var gifCellHeight = toPrecision(gifImgHeight / that.editSpot.info.animateInfo.cellYcount,1);
$("#gifCellHeight").text(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()
})*/
$("#voidCount").on('change',(e)=>{
strictInputNum(e, 0);
that.editSpot.info.animateInfo.voidCount = parseInt(e.target.value)
changeFrameCount()
restartAnimation()
})
let gifDurationFun = function(value){
var a = that.editSpot.info.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 = that.editSpot.info.animateInfo
let frameCount = a.cellXcount * a.cellYcount - (a.voidCount||0)
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()
})
}
this.modelMenuOptions = new MenuOptions({
dom: this.hotpointDetail.find(".MenuOptions[name=modelType]"),
uiCallBack : (o)=>{
var name = o.name == void 0 ? o.$li.attr('index') : o.name
if(name == "default"){
this.hotpointDetail.find('[name=boxDepthPanel]').removeClass('hide')
this.updateBoxDepthPanel()
this.hotpointDetail.find('[name=uploadObj]').addClass('hide')
transformControls.unableScaleZ()
}else{
this.hotpointDetail.find('[name=boxDepthPanel]').addClass('hide')
this.hotpointDetail.find('[name=uploadObj]').removeClass('hide')
}
},
callbackWhenChose:(o)=>{
var name = o.$li.attr('index')
if(name == "default"){
/* transformControls.unableScaleZ()
this.editSpot.removeModel() */
this.switchModel({remove:true, spot:this.editSpot})
if(this._scale[this.editSpot.texType]){//恢复大小
this.editSpot.scale.copy(this._scale[this.editSpot.texType]);
this.editSpot.info.scale.copy(this._scale[this.editSpot.texType]);
}
}else{
this.modelList.options.selectFun()
this._scale[this.editSpot.texType] = this.editSpot.scale.clone()
}
}
})
this.titleShowOptions = new MenuOptions({ //何时显示
dom: this.hotpointDetail.find(".MenuOptions[name=titleShowType]"),
uiCallBack : (o)=>{
},
callbackWhenChose:(o)=>{
var name = o.name == void 0 ? o.$li.attr('index') : o.name
this.editSpot.info.titleShowType = name
this.editSpot.setHoverState(false) //update
}
})
this.titlePosOptions = new MenuOptions({ //相对热点的位置
dom: this.hotpointDetail.find(".MenuOptions[name=titlePos]"),
uiCallBack : (o)=>{
},
callbackWhenChose:(o)=>{
var name = o.name == void 0 ? o.$li.attr('index') : o.name
this.editSpot.info.titlePos = name
this.editSpot.setTitleDir();
this.latestTitlePos = this.editSpot.info.titlePos//最近一次设置的,运用到新的热点中
}
})
this.hotpointDetail.find("li[name='fastTran'] button").on('click',(e)=>{
this.setCameraBtn(!this.gettingCameraData)
})
{
let pos = new THREE.Vector3(Infinity,Infinity,Infinity)
player.on("view.changed",(e)=>{
if(e.cameraChanged && !pos.equals(player.position)){
this.updateDis();
pos.copy(player.position)
}
})
}
}
Hotpoint.prototype.setCameraBtn = function(state){
let btn = this.hotpointDetail.find("li[name='fastTran'] button")
if(!state){
confirmSnap.addClass("hide");
snapshotGui.hide();
btn.text('设置')
this.gettingCameraData = false
}else{
confirmSnap.removeClass("hide");
$('#camera-start').text("点此设置跳转到此方位")
snapshotGui.show();
if (player.mode != "panorama"){
$(".confirmSnap").addClass("unable")
}else{
$(".confirmSnap").removeClass("unable")
}
btn.text('结束设置')
this.gettingCameraData = true
}
}
Hotpoint.prototype.updateBoxDepthPanel = function(){
var hot = this.editSpot
if (hot.info.hasBox) {
this.scroller.boxDepth.setValue(hot.scale.z * 100, true)
} else {
this.scroller.boxDepth.setValue(0, true)
}
setTimeout(()=>{
this.scroller.boxDepth.InitOffset()
}, 201)
}
/**
* 显示编辑热点的窗口和初始化热点窗口的数据
*/
Hotpoint.prototype.editHot = function(hot, $li) {
try {
transformControls.attach(hot)
if(player.mode == 'panorama'){
hot.examine( {
dontOpen: true, examine:true,
dontFastTran: true,
aimDuration : 600,
duration : 600
})
}else{
player.focusPoint({aim: hot.position, radius:hot.position.distanceTo(player.position)})
}
} catch (e) {}
if(this.editSpot == hot)return
this.hotpointDetail.removeClass("atRight");
$("#hotpointDetail .audio.mediaUpload").find("input").val('');
var playIcon = 'images/play.png';
this.editSpot = hot
transformControls.transformMenuOptions.updateChoseAtUI({name:'translate'}) //$(".MenuOptions[name='transform'] li[index='translate']").click()//transformControls.transCtlChangeMode("translate")
this.getTempInfo(hot)
hot.visible = true
this.updatePano()
this.updateListSelect(hot);
//$("#isSprite")[0].checked = this.editSpot.info.isSprite
this.isSpriteCheckBox.updateChoseAtUI(this.editSpot.info.isSprite)
this.imgDescCheckBox.updateChoseAtUI(this.editSpot.info.useImgDesc)
this.linkTypeMenuOptions.updateChoseAtUI({name:this.editSpot.info.linkType})
this.updateClickEventUI();//根据actionType更新ui
var iframesHTML = hot.info.iframe.map(function(iframe) {
return this.inputList("请填写网页链接", iframe)
}.bind(this))
var modulesHTML = hot.info.model.map(function(module) {
return this.inputList("请填写网页链接", module)
}.bind(this))
var imagesHTML = hot.info.images.map(function(image,index) {
return ''
})
var videosHTML = hot.info.video.map(function(ly) {
var thumb = (!ly.img || ly.img === "undefined") ? '' : '
'
var thumbResult = (!ly.img || ly.img === "undefined") ? '' : 'success';
var dom = ''
return dom
})
this.hotpointDetail.find(".name > input").val(hot.info.title);
this.hotpointDetail.find('[name="intro"] .editText').val(hot.info.content);
this.hotpointDetail.find("[name=photo] .list").html(imagesHTML);
this.hotpointDetail.find("[name=video] .list").html(videosHTML);
this.hotpointDetail.find("[name=modelSrc] .list").html(modulesHTML);
this.hotpointDetail.find("[name=webPage] .list").html(iframesHTML);
Array.from(this.hotpointDetail.find("[name=photo] .list .descBtn")).forEach((btn,index)=>{
this.imgDescBtnBind(btn, this.editSpot.info.imagesDesc[index])
this.imgDescBtnUpdate(btn,index)
})
this.imgDescBtnChose(null)
let bgName = hot.info.bgName || '热点背景音乐';
if (hot.info.backgroundMusic) {
this.musicBox.show(/* this.hotpointDetail.find(".audio.mediaUpload"), */bgName, hot.info.backgroundMusic)
} else {
this.musicBox.hide()
}
{//跳转方位设置
var preview = $('#hotpointDetail .shotImg.innerBtn')[0]
preview.cameraData = hot.info.cameraData
if(hot.info.cameraData){
preview.style['background-image'] = "url(" + hot.info.cameraData.thumbImg + ")"
}else{
preview.style['background-image'] = ''
}
}
{//标题显示
this.titleShowOptions.updateChoseAtUI({name:this.editSpot.info.titleShowType})
this.titlePosOptions.updateChoseAtUI({name:this.editSpot.info.titlePos})
}
$('#setPosForPano [name="dis"]').removeClass('hide');
this.updateDis()
}
Hotpoint.prototype.updateDis = function(){
if(!this.editSpot)return
var pos = this.editSpot.position;
var playerPos = player.position;
var dis1 = pos.clone().setY(0).distanceTo(playerPos.clone().setY(0))
var disY = pos.y - playerPos.y
var dir = disY>0 ? '上' : '下'
$('#setPosForPano [name="dis"]').html(`与相机水平距离: ${toPrecision(dis1, 2)}m ,
在相机之${dir}: ${toPrecision(Math.abs(disY), 2)}m`)
}
Hotpoint.prototype.recoverInfo = function(hot) { // 恢復
hot.info = hot.tempInfo;
hot.setFromInfo(hot.info, hot.tempInfo.media, hot.tempInfo.objObject)
delete hot.info.media
delete hot.info.objObject
}
Hotpoint.prototype.getTempInfo = function(hot) { // 编辑前, 从当前状态获取info, 用於恢復
var plane = hot.plane;
var info = hot.info;
hot.tempInfo = CloneObject(info);
hot.tempInfo.media = hot.texMedia
hot.tempInfo.objObject = hot.objObject
this.getTempInfos()
}
Hotpoint.prototype.getTempInfos = function(){
if(Hot.allPhotoLoaded && Hot.allModelLoaded){
this.tempInfos = {}
player.model.hotGroup.children.forEach(hot=>{
this.tempInfos[hot.sid] = {
styleImg : hot.styleImg,
texMedia : hot.texMedia,
objObject : hot.objObject,
scale : hot.scale.clone()
}
})
}
}
Hotpoint.prototype.getTransformAtPano = function(type){
/* var name = getTransformSid()
var info = {
pos : this.editSpot.mesh.position.clone()
}
if(!this.editSpot.isSprite){
info.qua = this.editSpot.mesh.quaternion.clone()
}else{
if(type == 'quaternion')return; //如果恒朝向相机且调整的是quaternion,不要保存position
}
this.editSpot.transformAtPanos[name] = info */
//this.editSpot.usingTransformData = true
var name = getTransformSid()
this.editSpot.info.transformAtPanos[name] = {
pos : this.editSpot.position.clone()
}
}
Hotpoint.prototype.updateTransform = function(type){
var on = this.panoTransformCheckBox.checked() //$('#setPosForPano input').is(':checked')
//var name = getTransformSid()
if(on && type == 'position'){
this.getTransformAtPano(type)
}else{
if(type == 'position'){
this.editSpot.info.position.copy(this.editSpot.position)
}else if(type == 'quaternion'){
if(!this.editSpot.isSprite){ //如果恒朝向相机就不保存quaternion
this.editSpot.info.rotation.copy(this.editSpot.rotation)
}
}else if(type == 'scale'){
this.editSpot.info.scale.copy(this.editSpot.scale)
}
}
type == 'position' && this.updateDis()
}
Hotpoint.prototype.updatePano = function(){
if(!this.editSpot ) return;
//$('#setPosForPano input').prop('checked', !!this.editSpot.info.transformAtPanos[getTransformSid()]);
this.panoTransformCheckBox.updateChoseAtUI(!!this.editSpot.info.transformAtPanos[getTransformSid()])
}
var ifSameTex = function(imgs0, imgs1){//是否是相同的图 (两个都是空的不算相同)
return !!(imgs0[0] && imgs1[0] && imgs0[0].src == imgs1[0].src &&
(imgs0[1] ? (imgs1[1] && imgs0[1].src == imgs1[1].src) : !imgs1[1] ))
}
Hotpoint.prototype.findSpotByContent = (media, type)=>{////使用了该贴图的所有热点
var spots = []
if(type == 'shine'){
media = media || []
for(var i in player.model.hots){
if(player.model.hots[i].texType != type)continue
var styleImg = player.model.hots[i].styleImg || [];
if(ifSameTex(styleImg, media)){
spots.push(player.model.hots[i])
}
}
}else if(type == 'photo' || type == 'video'){
if(type == 'photo' && !Hot.allPhotoLoaded)return spots
for(var i in player.model.hots){
if(player.model.hots[i].texType != type)continue
var texMedia = player.model.hots[i].texMedia
if(media && texMedia && media.src == texMedia.src){
spots.push(player.model.hots[i])
}
}
}else if(type == 'model'){
if(!Hot.allModelLoaded)return spots
for(var i in player.model.hots){
if(!player.model.hots[i].objObject)continue
var objObject = player.model.hots[i].objObject
if(media && objObject && media.src == objObject.src){
spots.push(player.model.hots[i])
}
}
}
return spots
}
Hotpoint.prototype.initListSelect = function(){//热点样式图列表
var that = this;
var countElem = $("")
var uploadInputImage = $('');
var uploadInputVideo = $('');
var uploadInputModel = $('');
var getListItem = ()=>{
var elem = $('')
elem[0]._styleImg = []
return elem
}
var editItemInfo = {}
var setImgContent = function($dom, index, src) {
var li = $dom.find('li').eq(index)
var div = li.find('>div');
if (src) {
li.addClass("uploaded")
div.css("background-image", `url(${src})`)
} else {
li.removeClass("uploaded")
div.css("background-image", '')
}
}
var hotIcons = []; // 从所有热点tex中搜集 。
player.model.hotGroup.children.forEach(e=>{// 从所有热点tex中搜集
if(e.texType == 'shine'){
let imgs = e.info.styleImg;
if(imgs && imgs.length){
if(!hotIcons.find(e=>e[0] == imgs[0] && e[1] == imgs[1])){
hotIcons.push(imgs)
}
}
}
})
hotIcons = hotIcons.map(imgs=>imgs = imgs.map((a)=>{return {src:a}}))
//hotIcons = [[], [g_HotImage.point, g_HotImage.point2], ...hotIcons]
hotIcons.push([{src:g_HotImage.point}, {src:g_HotImage.point2}],[] )//放末尾用来添加的 g_HotImage是默认
var list = hotIcons.map(arr=>{//初始列表
var elem = getListItem()
elem[0]._styleImg = arr //每个li上绑定一个 _styleImg,存储它包含的图, 和热点的styleImg对应
var divs = elem.find("li>div")
arr.forEach((img,i)=>{
setImgContent(elem, i, img.src)
})
arr.length && elem.find("li").eq(1).removeClass('hide')
return elem
})
list[list.length - 2].addClass('forbitEdit')
this.styleList = new ListBox(list, $('#shineTexSelect'), {//列表
selectFun:(o={})=>{//选中时要改变选中项selection缩略图 以及改变热点
if(this.styleList.chosenItem == void 0){
this.styleList.listTitle.find('li').addClass('hide')
}else{
this.styleList.listTitle.find('li').removeClass('hide')
var divs = this.styleList.listTitle.find('li>div')//selection
var imgs = this.styleList.chosenItem[0]._styleImg;
if(imgs[0]){
divs.eq(0).css("background-image", 'url("'+imgs[0].src+'")')
divs.eq(0).parent().removeClass('hide')
}else{
divs.eq(0).parent().addClass('hide')
}
if(imgs[1]){
divs.eq(1).css("background-image", 'url("'+imgs[1].src+'")')
divs.eq(1).parent().removeClass('hide')
}else{
divs.eq(1).parent().addClass('hide')
}
//应用到热点:
o.dontApplyToHot || this.editSpot.changeShineTex(imgs)
}
Array.from(this.styleList.listDom.children()).forEach(li=>{//更新一下所有的li的使用的spot
li.sameContentSpots = this.findSpotByContent(li._styleImg, 'shine')
})
},
/* delFun: ()=>{
}, */
addFun: ($li)=>{ //列表新增时对li的操作
$li[0].sameContentSpots = this.findSpotByContent($li[0]._styleImg, 'shine')
$li.find('li').bind('click', (e)=>{
e.stopPropagation()
var index = $(e.currentTarget).index();
if($li.hasClass('forbitEdit'))return
if (e.target.classList.contains("del")) { //删除图片
if ($li[0]._styleImg.length == 2 && index == 0) { //删除第一个 且有第二个的话
setImgContent($li, 0, $li[0]._styleImg[1].src);
setImgContent($li, 1, null);
$li[0]._styleImg = [$li[0]._styleImg[1]]
} else {
setImgContent($li, index, null);
$li[0]._styleImg.pop()
if ($li[0]._styleImg.length == 0) {
//$li.find("li").eq(1).addClass("hide");
this.styleList.removeItem($li)
}
}
$li[0].sameContentSpots.forEach(hot=>{
hot.changeShineTex($li[0]._styleImg)
})
if($li.hasClass('selected')){//是当前spot的
//this.editSpot.changeTex($li[0]._styleImg)
this.styleList.options.selectFun()
}
} else {
//添加图片
uploadInputImage.click()
editItemInfo = {
imgs : $li[0]._styleImg, index, $li , type:"shine"
};
}
})
$li.bind('mouseover', (e)=>{
/* this.showTitileSpots = $li[0].sameContentSpots;
this.showTitileSpots.forEach(a=>a.showTitle()) */
countElem.text("热点个数:"+$li[0].sameContentSpots.length).removeClass('hide')
$li.append(countElem)
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(true)
})
})
$li.bind('mouseout', (e)=>{
/* this.showTitileSpots.forEach(a=>a.hideTitle())
this.showTitileSpots = null; */
countElem.addClass('hide')
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(false)
})
})
},
saveTemp: (list)=>{//编辑热点时保存一份副本
list._styleImgTemp = Array.from(list.listDom.children()).map((li)=>{
return li._styleImg.slice()
})
},
recover : (list)=>{//取消编辑时恢复
Array.from(list.listDom.children()).forEach((li,i)=>{
li._styleImg = list._styleImgTemp[i]
li.sameContentSpots = this.findSpotByContent(li._styleImg, 'shine')
})
},
})
this.styleList.findChosenByContent = (imgs=[])=>{//找到某图对应的li
var list = Array.from(this.styleList.listDom.children())
var item = list.find(e=>ifSameTex(e._styleImg, imgs ))
return {index: item ? list.indexOf(item) : null, item: item }
}
/* this.styleList.clearVoid = ()=>{//清理空的
var length = this.styleList.listDom.children().length;
Array.from(this.styleList.listDom.children()).forEach((e, i)=>{
if(i > 0 ){
if(e._styleImg.length == 0) this.styleList.removeItem($(e))
}
})
} */
this.styleList.addNew = ()=>{//看是否在第一行增加新的
/* var lastOne = this.styleList.listDom.children().last();
if(lastOne[0]._styleImg.length != 0){
this.styleList.addItem(getListItem())
} */
let firstOne = this.styleList.listDom.children().first();
if(firstOne[0]._styleImg.length != 0){
this.styleList.addItem(getListItem())
}
}
//-----photo----video-----------------------
var getPhotoListItem = ()=>{
var elem = $('')
return elem
}
var getVideoListItem = ()=>{
var elem = $('')
return elem
}
var photos = [] ,videos = []
var photoList = [], videoList = []
player.model.hotGroup.children.forEach(hot=>{
if(hot.texType == 'photo'){
var media = hot.texMedia
if(!photos.find(u=>media == u)){
photos.push(media)
var elem = getPhotoListItem()
elem[0]._media = media
elem[0].animateInfo = CloneObject(hot.info.animateInfo)
elem.find(".upload>div").css("background-image", "url(" + hot.info.texSrc + ")")
elem.find(".upload").addClass("uploaded")
photoList.push(elem)
}
}else if(hot.texType == 'video'){
var media = hot.texMedia
if(!videos.find(u=>media == u)){
videos.push(media)
var elem = getVideoListItem()
elem[0]._media = media
elem.attr("title", media.name)
elem.find(".upload>div").text(media.name)
elem.find(".upload").addClass("uploaded")
videoList.push(elem)
}
}
})
photoList.push(getPhotoListItem())//放末尾用来添加的
this.photoList = new ListBox(photoList, $('#photoTexSelect'), {//列表
selectFun:(o={})=>{//选中时要改变选中项selection缩略图 以及改变热点
var div = this.photoList.listTitle.find('.uploaded')//selection
var media;
if(this.photoList.chosenItem){
media = this.photoList.chosenItem[0]._media;
}
if(media){
div.removeClass('hide')
div.css("background-image", 'url("'+media.src+'")')
//应用到热点:
if(!o.dontApplyToHot){
this.editSpot.changeTexType("photo", media || 'clear' )
this.updateGifPanel({animateInfo: this.photoList.chosenItem[0].animateInfo })
this.useSuitableRatio()
}else{
this.updateGifPanel({on: !!this.photoList.chosenItem[0].animateInfo })
}
$('#gifEdit').removeClass('hide');
}else{
!o.dontApplyToHot && this.editSpot.changeTexType("photo", 'clear' )
this.updateGifPanel({on:false})
$('#gifEdit').addClass('hide');
div.addClass('hide')
}
Array.from(this.photoList.listDom.children()).forEach(li=>{//更新一下所有的li的使用的spot
li.sameContentSpots = this.findSpotByContent(li._media, 'photo')
})
},
addFun: ($li)=>{ //photoList列表新增时对li的操作
$li[0].sameContentSpots = this.findSpotByContent($li[0]._media, 'photo')
$li.find('.upload').bind('click', (e)=>{
e.stopPropagation()
var index = $(e.currentTarget).index();
if (e.target.classList.contains("del")) { //删除图片
/* if($li.hasClass('selected')){//(肯定)是当前spot的
that.editSpot.changeTexType('photo', 'clear')
}
$li[0]._media = null */
this.photoList.removeItem($li)
} else {
//添加图片
uploadInputImage.click()
editItemInfo = {
$li , type:"photo"
};
}
})
$li.bind('mouseover', (e)=>{
/* this.showTitileSpots = $li[0].sameContentSpots;
this.showTitileSpots.forEach(a=>a.showTitle()) */
countElem.text("热点个数:"+$li[0].sameContentSpots.length).removeClass('hide')
$li.append(countElem)
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(true)
})
})
$li.bind('mouseout', (e)=>{
/* this.showTitileSpots.forEach(a=>a.hideTitle())
this.showTitileSpots = null; */
countElem.addClass('hide')
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(false)
})
})
},
saveTemp: (list)=>{//编辑热点时保存一份副本
list._mediaTemp = Array.from(list.listDom.children()).map((li)=>{
return li._media
})
list._animationTemp = Array.from(list.listDom.children()).map((li)=>{
return li.animateInfo
})
},
recover : (list)=>{//取消编辑时恢复
Array.from(list.listDom.children()).forEach((li,i)=>{
li._media = list._mediaTemp[i]
li.animateInfo = list._animationTemp[i]
li.sameContentSpots = this.findSpotByContent(li._media, 'photo')
})
},
})
this.photoList.addNew = ()=>{//看是否在第一行增加新的
let firstOne = this.photoList.listDom.children().first();
if(firstOne[0]._media){
this.photoList.addItem(getPhotoListItem())
}
}
//---videoList-------
videoList.push(getVideoListItem())//放末尾用来添加的
this.videoList = new ListBox(videoList, $('#videoTexSelect'), {//列表
selectFun:(o={})=>{
var div = this.videoList.listTitle//selection
var media;
if(this.videoList.chosenItem){
media = this.videoList.chosenItem[0]._media;
}
if(media){
//div.removeClass('hide')
div.text(media ? media.name : '')
//应用到热点:
this.editSpot.info.texSrc = media && media.src //视频不能共用一个,否则会一起播放暂停
this.editSpot.info.fileName = media.name
this.editSpot.videoWidth = media.videoWidth //记录。因为新new的话要等一会儿才不为0
this.editSpot.videoHeight = media.videoHeight
//media.currentTime = 0 //触发oncanplaythrough
if(!o.dontApplyToHot){
this.editSpot.changeTexType("video" , media ? null : 'clear' )
this.useSuitableRatio()
}
}else{
//div.addClass('hide')
div.text('')
if(!o.dontApplyToHot){
this.editSpot.changeTexType("video" , 'clear' )
}
}
Array.from(this.videoList.listDom.children()).forEach(li=>{//更新一下所有的li的使用的spot
li.sameContentSpots = this.findSpotByContent(li._media, 'video')
})
},
addFun: ($li)=>{
$li[0].sameContentSpots = this.findSpotByContent($li[0]._media, 'video')
$li.find('.upload').bind('click', (e)=>{
e.stopPropagation()
var index = $(e.currentTarget).index();
if (e.target.classList.contains("del")) { //删除
if($li.hasClass('selected')){//是当前spot的
that.editSpot.changeTexType('video', 'clear')
}
$li[0]._media = null
this.videoList.removeItem($li)
} else {
//添加
uploadInputVideo.click()
editItemInfo = {
$li , type:"video"
};
}
})
$li.bind('mouseover', (e)=>{
/* this.showTitileSpots = $li[0].sameContentSpots;
this.showTitileSpots.forEach(a=>a.showTitle()) */
countElem.text("热点个数:"+$li[0].sameContentSpots.length).removeClass('hide')
$li.append(countElem)
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(true)
})
})
$li.bind('mouseout', (e)=>{
/* this.showTitileSpots.forEach(a=>a.hideTitle())
this.showTitileSpots = null; */
countElem.addClass('hide')
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(false)
})
})
},
saveTemp: (list)=>{//编辑热点时保存一份副本
list._mediaTemp = Array.from(list.listDom.children()).map((li)=>{
return li._media
})
},
recover : (list)=>{//取消编辑时恢复
Array.from(list.listDom.children()).forEach((li,i)=>{
li._media = list._mediaTemp[i]
li.sameContentSpots = this.findSpotByContent(li._media, 'video')
})
},
})
this.videoList.addNew = ()=>{//看是否在第一行增加新的
let firstOne = this.videoList.listDom.children().first();
if(firstOne[0]._media){
this.videoList.addItem(getVideoListItem())
}
}
this.photoList.findChosenByContent = this.videoList.findChosenByContent = (list_, media)=>{//找到某图对应的li
var list = Array.from(list_.listDom.children())
var item = list.find(e=>e._media && media && e._media.src == media.src)
return {index: item ? list.indexOf(item) : null, item: item }
}
/* this.photoList.clearVoid = this.videoList.clearVoid = (list_)=>{//清理空的
var length = list_.listDom.children().length;
Array.from(list_.listDom.children()).forEach((e, i)=>{
if(i > 0 ){
if(!e._media ) list_.removeItem($(e))
}
})
} */
//----modelList---------------------
var objSrcs = []
var modelList = []
var getModelListItem = ()=>{
var elem = $('')
return elem
}
player.model.hotGroup.children.forEach(e=>{
if(e.info.objSrc && !objSrcs.find(u=>e.info.objSrc == u)){
objSrcs.push(e.info.objSrc)
var elem = getModelListItem()
elem[0].objObject = e.objObject
elem.attr("title", e.info.objName)
elem.find(".upload>div").text(e.info.objName)
elem.find(".upload").addClass("uploaded")
modelList.push(elem)
}
})
modelList.push(getModelListItem())//放末尾用来添加的
this.modelList = new ListBox(modelList, $('#ObjSelect'), {//列表
selectFun:(o={})=>{
var div = this.modelList.listTitle//selection
var model;
if(this.modelList.chosenItem){
model = this.modelList.chosenItem[0].objObject;
}
if(model){
//div.removeClass('hide')
div.text(model ? model.name : '')
//应用到热点:
if(!o.dontApplyToHot){
this.switchModel({add:model,spot:this.editSpot})
}
}else{
//div.addClass('hide')
div.text('')
this.switchModel({remove:true,spot:this.editSpot})
}
Array.from(this.modelList.listDom.children()).forEach(li=>{//更新一下所有的li的使用的spot
li.sameContentSpots = this.findSpotByContent(li.objObject, 'model')
})
},
addFun: ($li)=>{
$li[0].sameContentSpots = this.findSpotByContent($li[0].objObject, 'model')
$li.find('.upload').bind('click', (e)=>{
e.stopPropagation()
var index = $(e.currentTarget).index();
if (e.target.classList.contains("del")) { //删除
$li[0].sameContentSpots.forEach(e=>{
/* e.removeModel() */
that.switchModel({remove:true, spot:e})
})
if($li.hasClass('selected')){//是当前spot的 ui..
}
$li[0].objObject = null
this.modelList.removeItem($li)
} else {
//添加
uploadInputModel.click()
editItemInfo = {
$li , type:"model"
};
}
})
$li.bind('mouseover', (e)=>{
/* this.showTitileSpots = $li[0].sameContentSpots;
this.showTitileSpots.forEach(a=>a.showTitle()) */
countElem.text("热点个数:"+$li[0].sameContentSpots.length).removeClass('hide')
$li.append(countElem)
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(true)
})
})
$li.bind('mouseout', (e)=>{
/* this.showTitileSpots.forEach(a=>a.hideTitle())
this.showTitileSpots = null; */
countElem.addClass('hide')
$li[0].sameContentSpots.forEach(hot=>{
hot.changeBoxHelperDisplay(false)
})
})
},
saveTemp: (list)=>{//编辑热点时保存一份副本
list._objTemp = Array.from(list.listDom.children()).map((li)=>{
return li.objObject
})
},
recover : (list)=>{//取消编辑时恢复
Array.from(list.listDom.children()).forEach((li,i)=>{
li.objObject = list._objTemp[i];
li.sameContentSpots = this.findSpotByContent(li.objObject, 'model')
})
},
})
this.modelList.addNew = ()=>{//看是否在第一行增加新的
let firstOne = this.modelList.listDom.children().first();
if(firstOne[0].objObject){
this.modelList.addItem(getModelListItem())
}
}
this.modelList.findChosenByContent = (objObject)=>{
var list = Array.from(this.modelList.listDom.children())
var item = list.find(e=>e.objObject && e.objObject.src == objObject.src)
return {index: item ? list.indexOf(item) : null, item: item }
}
this.photoList.updateDelBtns = this.videoList.updateDelBtns = (list_)=>{//每次开始编辑热点时更新删除按钮可见性
Array.from(list_.listDom.children()).forEach(li=>{
//li.sameContentSpots = this.findSpotByContent(li._media, 'photo')
if(li.sameContentSpots.find(e=>e!=this.editSpot)){
$(li).addClass('cannotDelete')
}else{
$(li).removeClass('cannotDelete')
}
})
}
//-----------------------------------
uploadInputImage.on("change", (e)=>{
inputMedia({
enableTypes: ["photo"],
photoDone: (resultImg)=>{
if(editItemInfo.type == 'shine'){
editItemInfo.imgs[editItemInfo.index] = resultImg //{file: resultImg.file, needSave:true, src:resultImg.src}//resultImg
setImgContent(editItemInfo.$li, editItemInfo.index, resultImg.src)
if (editItemInfo.index == 0){
editItemInfo.$li.find('li').eq(1).removeClass("hide");
}
resultImg.needSave = true
editItemInfo.$li[0].sameContentSpots.forEach(hot=>{
hot.changeShineTex(editItemInfo.$li[0]._styleImg)
})
}else{//"photo"
editItemInfo.$li.find(".upload").addClass("uploaded")
editItemInfo.$li.find(".upload div").css("background-image", `url(${resultImg.src})`)
editItemInfo.$li[0]._media = resultImg
editItemInfo.$li[0].sameContentSpots.forEach(hot=>{
hot.changeTexType("photo",resultImg)
})
resultImg.needSave = true
}
/* if(editItemInfo.$li.hasClass('selected')){//是当前spot的
this.texLists[editItemInfo.type].options.selectFun({dontApplyToHot:true})//更新选中状态
} */
this.texLists[editItemInfo.type].addNew()
this.texLists[editItemInfo.type].selectFromOutSide(editItemInfo.$li.index())
this.texLists[editItemInfo.type].listDom.addClass('hide')
}
}, "photo", e);
})
uploadInputVideo.on("change", (e)=>{
inputMedia({
enableTypes: ["video"],
videoDone: (file,video)=>{
editItemInfo.$li.find(".upload").addClass("uploaded")
editItemInfo.$li.find(".upload>div").text(file.name)
editItemInfo.$li.attr("title", file.name)
video.file = file
video.name = file.name
video.needSave = true
editItemInfo.$li[0]._media = video
editItemInfo.$li[0].sameContentSpots.forEach(hot=>{
hot.info.texSrc = video.src //视频不能共用一个,否则会一起播放暂停
hot.info.fileName = video.name
hot.videoWidth = video.videoWidth //记录。因为新new的话要等一会儿才不为0
hot.videoHeight = video.videoHeight
hot.changeTexType("video" )
})
/* if(editItemInfo.$li.hasClass('selected')){//是当前spot的
this.videoList.options.selectFun({dontApplyToHot:true})//更新选中状态
} */
this.videoList.addNew()
this.videoList.selectFromOutSide(editItemInfo.$li.index())
}
}, "video", e);
})
uploadInputModel.on("change", (e)=>{
inputMedia({
enableTypes: ["model"],
modelDone: (file,object)=>{
editItemInfo.$li.find(".upload").addClass("uploaded")
editItemInfo.$li.find(".upload>div").text(file.name)
editItemInfo.$li.attr("title", file.name)
object.file = file
object.name = file.name
object.src = object.uuid;//作为标识而已
object.needSave = true
{//adjustModelAuto
let bound = new THREE.Box3
object.traverse( function ( child ) {
if(child.geometry){
child.geometry.computeBoundingBox();
bound.union(child.geometry.boundingBox)
}
});
let standard = 1;
let size = bound.max.distanceTo(bound.min);
let s = standard / size
object.scale.set(s,s,s)
let center = bound.center()
object.position.copy(center).negate().multiplyScalar(s)//保证模型的中心点和hot中心点重合
object.modelBound = {
bound,
scaleRatio : s,
position: object.position.toArray()
}
}
editItemInfo.$li[0].objObject = object
editItemInfo.$li[0].sameContentSpots.forEach(hot=>{
//hot.addModel(object)
this.switchModel({add:object, spot:hot})
})
this.modelList.selectFromOutSide(editItemInfo.$li.index())
/* if(editItemInfo.$li.hasClass('selected')){//是当前spot的
this.modelList.options.selectFun({dontApplyToHot:true})//更新选中状态
} */
this.modelList.addNew()
}
}, "model", e);
})
this.texLists = {shine: this.styleList, photo:this.photoList, video: this.videoList}
this.texTypeMenuOptions = new MenuOptions({
dom: this.hotpointDetail.find(" li[name=style] .MenuOptions"),
uiCallBack : (o)=>{
var name = o.name == void 0 ? o.$li.attr('index') : o.name
for(let i in this.texLists){ this.texLists[i].listDom.parent().addClass("hide")}
this.texLists[name].listDom.parent().removeClass("hide")
if(name == 'photo'){
$('#gifEdit').removeClass('hide')
}else{
$('#gifEdit').addClass('hide')
this.updateGifPanel({on:false})
}
},
callbackWhenChose:(o)=>{
this.changeType( o.$li.attr('index'))
}
})
//编辑开放
this.hotpointDetail.find(" li[name=style]").removeClass('unable');
this.hotpointDetail.find(" li[name=model]").removeClass('unable');
this.hotpointDetail.find(" li[name=style] .itemTitle").attr('data-size','')
if(this.editSpot){//已经在编辑了,初始化下
this.updateListSelect(this.editSpot)
this.getTempInfos()
}
this.hotpointDetail.find(" li[name=setPos] button[name=setSpace] ").on('click',(e)=>{
var space = transformControls.space == 'world'?'local':'world'
transformControls.setSpace(space)
e.target.innerText = space == 'world'?'切换为世界坐标方向':'切换为本地坐标方向'
})
this.hotpointDetail.find(" li[name=setPos] button[name=useSuitableRatio] ").on('click',()=>{
this.useSuitableRatio()
})
this.hotpointDetail.find(" li[name=setPos] button[name=resetRot] ").on('click',()=>{
this.editSpot.rotation.x = 0
this.editSpot.rotation.z = 0
})
}
Hotpoint.prototype.switchModel = function(o={}){
if(o.add){
var model = o.add.clone();
o.spot.info.objSrc = o.add.src
o.spot.info.objName = o.add.name
o.spot.info.modelBound = o.add.modelBound;
o.spot.addModel(model)
var s = 1;//暂时
o.spot.scale.set(s,s,s)//恢复成等大比例,方便用户看清原始比例
o.spot.info.scale.set(s,s,s)
//this.updateTransform('scale')
if(o.spot == this.editSpot){
transformControls.enableScaleZ()
}
}else if(o.remove){
//如果没有出现plane,很可能是因为背面朝向镜头了!
o.spot.addPlane()
if(o.spot == this.editSpot) transformControls.unableScaleZ()
}
}
Hotpoint.prototype.changeType = function(type){
var hot = this.editSpot
var list
this._scale[hot.texType] = hot.scale.clone()
if(type == 'shine'){
hot.changeTexType(type, 'clear')
if(hot.styleImg){
hot.changeTexType(type, hot.styleImg )
}
list = this.styleList
list.selectFromOutSide(list.chosenIndex || 1)//触发选择函数
}else{
hot.changeTexType(type,'clear')
if(type == 'photo'){
list = this.photoList
}else{
list = this.videoList
}
list.selectFromOutSide(list.chosenIndex)
}
this.useSuitableRatio({setScaleAuto:true})
hot.info.actionType = CloneObject(settings.hotClickEvent[type]);//给一个默认 图和视频不打开热点
/* if(type == 'video'){
hot.info.actionType.playAndPause = true;
}else{
delete hot.info.actionType.playAndPause
} */
if(type != 'video'){
delete hot.info.fileName
}
this.updateClickEventUI();//根据actionType更新ui
}
Hotpoint.prototype.updateGifPanel = function(o={}){
var hot = this.editSpot
if(!hot.material_.map)return;
let a = o.animateInfo || hot.info.animateInfo
//换图时根据图片的animation更改开关,如果有的话还要更改面板,如果图没有animation用自己的
if(o.animateInfo){//更换animateInfo
hot.info.animateInfo = CloneObject(o.animateInfo);
}
if("animateInfo" in o ){
o.on = !!o.animateInfo
}
if(!a){
o.on = false
}
if(o.on != void 0){
this.gifCheckBox.updateChoseAtUI(o.on)
GifTexDeal.remove(hot.animation)
if(o.on){
hot.animation = GifTexDeal.addAnimation(hot.material_.map, hot, hot.info.animateInfo, hot.sid)
GifTexDeal.start(hot.animation)
}else{
hot.animation = null
hot.info.animateInfo = null
}
}
let w = hot.material_.map.image.width
let h = hot.material_.map.image.height
if(a){
$("#gifXCount").val(a.cellXcount);
$("#gifYCount").val(a.cellYcount);
$("#gifImgWidth").text(w)
$("#gifImgHeight").text(h)
$("#gifCellWidth").text(toPrecision(w / a.cellXcount, 2));
$("#gifCellHeight").text(toPrecision(h / a.cellYcount, 2));
$("#voidCount").val(a.voidCount || 0);
let frameCount = a.cellXcount * a.cellYcount - (a.voidCount || 0)
$("#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").text(w);
$("#gifCellHeight").text(h)
$("#voidCount").val(0);
$("#gifFrameCount").text(1)
$("#gifDuration").val(1);
$("#gifFps").val(1);
}
}
Hotpoint.prototype.updateListSelect = function(hot) { //每次开始编辑热点时更新样式
if(!Hot.allPhotoLoaded || !Hot.allModelLoaded)return
var list = this.texLists[hot.texType];
var chosenIndex = null;
this.texTypeMenuOptions.updateChoseAtUI({name:hot.texType})
for(let i in this.texLists){
//this.texLists[i].clearVoid(this.texLists[i]);
this.texLists[i].saveTemp(this.texLists[i])
}
this.modelList.saveTemp()
if(hot.texType == 'shine'){
if (!hot.styleImg) hot.styleImg = [];
if(hot.styleImg.length){
var info = this.styleList.findChosenByContent(hot.styleImg)
chosenIndex = info.index
}
}else{
var info = list.findChosenByContent(list, hot.texMedia)
chosenIndex = info.index
}
list.selectFromOutSide(chosenIndex, {dontApplyToHot:true})
this.photoList.updateDelBtns(this.photoList)
this.videoList.updateDelBtns(this.videoList)
{//model
let hasModel = !!hot.objObject
this.modelMenuOptions.updateChoseAtUI({name: hasModel ? 'user' : 'default'})
if(hasModel){
var info = this.modelList.findChosenByContent(hot.objObject)
this.modelList.selectFromOutSide(info.index, {dontApplyToHot:true})
transformControls.enableScaleZ()
}
}
}
Hotpoint.prototype.useSuitableRatio = function(o={}) {//自适应素材比例
var hot = this.editSpot
var plane = this.editSpot.plane;
var w, h, defaultS = 1, s, mediaW, mediaH
if(this._scale[hot.texType] && o.setScaleAuto){
w = this._scale[hot.texType].x; h = this._scale[hot.texType].y;
}else{
if(hot.texType == 'shine'){//默认使用热点大小,正方形
if(o.setScaleAuto){
w = h = 1 //DATA.hotIconScale * g_HotMeshSize.g_HotMeshWidth
}else{
s = hot.scale.x * hot.scale.y
w = h = Math.sqrt(Math.abs(s))
}
}else{
if(!hot.material_.map)return
//假设不变总面积
if(o.setScaleAuto){
s = defaultS
}else{
s = hot.scale.x * hot.scale.y
}
if(hot.texType == 'photo'){
mediaW = hot.texMedia.width;
mediaH = hot.texMedia.height;
//动画的话再变
if(hot.info.animateInfo){
mediaW /= hot.info.animateInfo.cellXcount
mediaH /= hot.info.animateInfo.cellYcount
}
}else{
mediaW = hot.texMedia.videoWidth || hot.videoWidth || 1;
mediaH = hot.texMedia.videoHeight || hot.videoHeight || 1;
}
var k = Math.sqrt(Math.abs(s) / (mediaW * mediaH))
w = k * mediaW * (hot.scale.x < 0 ? -1 : 1);
h = k * mediaH * (hot.scale.y < 0 ? -1 : 1);
}
}
hot.scale.setX(w)
hot.scale.setY(h)
if(hot.isUserModel){
hot.scale.setZ(z)
}
this.updateTransform('scale')
},
Hotpoint.prototype.updateClickEventUI = function() {//根据actionType更新ui
var hot = this.editSpot;
/* var checkboxs = this.hotpointDetail.find("li[name='clickEvent'] li.editCheckbox");
checkboxs.addClass('hide');
for(let i in hot.info.actionType){
var checkbox = checkboxs.find('[name='+ i +']')
checkbox.parent().removeClass('hide');
checkbox[0].checked = !!hot.info.actionType[i]
}
var content = this.hotpointDetail.find("li[name='content']")
hot.info.actionType.openHot ? content.removeClass('hide') : content.addClass('hide') */
/* for(let i in hot.info.actionType){
this.actionCheckBox.updateChoseAtUI(hot.info.actionType[i], i)
} */
settings.hotClickActions.forEach(e=>{
this.actionCheckBox.updateChoseAtUI(hot.info.actionType[e], e)
})
}
//添加图片和视频
Hotpoint.prototype.addmediaInit = function() {
// 视频预览控制
var $videoLayout = $('.fun-view-video')
var that = this
$videoLayout.find('span').on('click', function() {
$videoLayout.hide();
$videoLayout.find('video').attr('src', '')[0].pause()
});
// 图片加载回调
function imageSuccess(file) {
if (!/image\/\w+/.test(file.type)) {
alert("文件必须为图片!");
return false;
}
if (!restrictedSize(file, 9)) {
return false;
}
var img = new Image()
img.src = URL.createObjectURL(file);
img.className = 'bg'
return img
}
// 视频加载回调
function videoSuccess(file, $elayout) {
if (!/video\/\w+/.test(file.type)) {
alert("视频必须为map4格式!");
return false;
}
$elayout.append('上传封面')
return '
'
}
// 视频封面回调
function thumbSuccess(file, $elayout, $seft) {
if (!/image\/\w+/.test(file.type)) {
alert("文件必须为图片!");
return false;
}
if (!restrictedSize(file, 2)) {
return false;
}
var img = $seft.closest('div').find('img.bg');
if(!img[0]){
img = $("
");
$seft.closest('div').find('a').append(img)
}
img.attr('src', URL.createObjectURL(file));
$seft.closest('span').removeClass("success")
}
// 图片与视频加载
function fileHandle(that) {
var $seft = $(this) //input
var file = this.files[0];
var type = this.activeElem ? this.activeElem.attr('data-type') : $seft.parent().attr('data-type');
var $din = $('')
var fnc = type === 'photo' ? imageSuccess : type === 'video' ? videoSuccess : thumbSuccess //再次传都会是thumSuccess
var $dom = fnc(file, $din, $seft)
if (type === 'photo' || type === 'video') {
if (!$dom)
return $seft.val('');
if(!this.activeElem){//创建新的item
var $layout = $seft.closest("li");
var $addLayout = $(document.createElement('a'));
$addLayout.attr("data-type", type)
var $close = $(document.createElement('span'));
$addLayout[0].file = file;
$addLayout.append($close);
$addLayout.append($dom);
$addLayout.addClass("result");
$din.prepend($addLayout);
$layout.find('.edit-fun-images').append($din);
if (type === 'photo'){
var $btn = $('添加描述
')
$din.append($btn)
that.imgDescBtnBind($btn[0])
}
}else{//重传
if (type === 'photo'){
this.activeElem.find("img.bg").remove();
}else{
this.activeElem.find(".play-video").remove();
}
this.activeElem.removeClass("success")
this.activeElem.append($dom)
this.activeElem[0].file = file;
this.value = ''
}
}
if (searchParent($seft[0], {
id: 'shareImgUpload'
})) {
//信息页面的分享图片
$("#shareImgUpload").addClass("hide")
}else if(searchParent($seft[0], {
id: 'SpotStyle'
})){
$("#SpotStyle").addClass("hide")
}
}
//用于重传的input
var imgInput = $("")
var videoInput = $("")
// 图片与视频加载
$('.upload, .edit-fun-images').on('change', function(ev) {
if (ev.target.tagName.toUpperCase() === 'INPUT') {
ev.target.files.length && fileHandle.call(ev.target, that)
}
})
imgInput.on('change', (ev)=>{fileHandle.call(ev.target, that)})
videoInput.on('change', (ev)=>{fileHandle.call(ev.target, that)})
$('.edit-fun-images').on('click', function(ev) {//点击item时
var $tag = $(ev.target)
var tagName = ev.target.tagName.toUpperCase()
if (tagName === 'SPAN') {
if (searchParent($tag[0], {
className: 'forShareImg'
})) {
//信息页面的分享图片
$("#shareImgUpload").removeClass('hide')
}else if(searchParent($tag[0], {
className: 'SpotStyle'
})){
$("#SpotStyle").removeClass('hide')
}
$tag.parent().parent().remove()
}else if (tagName === 'IMG' && $tag.hasClass('play-video')) {
$videoLayout.css('display', 'flex').find('video').attr('src', $tag.attr('videoURL'))[0].play()
}else{// 替换
var a = searchParent($tag[0], {
tagName: 'a'
})
if(a) {
var input
if(searchParent($tag[0], {
className: 'video'
})){
input = videoInput
}else{
input = imgInput
}
input[0].activeElem = $(a)
input.click()
}
}
})
}
Hotpoint.prototype.imgDescBtnUpdate = function(btn){//图片描述按钮状态更新
var $btn = $(btn)
/* if(index == void 0){
var btns = Array.from(this.hotpointDetail.find("[name=photo] .list .descBtn"))
index = btns.indexOf(btn)
} */
var desc = btn.desc
if(desc == void 0 || desc === ''){
$btn.removeClass('hasDesc')
$btn.text('添加描述')
}else{
$btn.addClass('hasDesc')
$btn.text('查看描述')
}
}
Hotpoint.prototype.imgDescBtnBind = function(btn, desc){//图片描述按钮事件
//console.log('imgDescBtnBind',btn)
var textarea = this.hotpointDetail.find('li[name="photo"] textarea');
var title = this.hotpointDetail.find('li[name="photo"] [name="descTitle"]')
btn.addEventListener('click',()=>{
this.hotpointDetail.find("[name=photo] .list .descBtn").removeClass('chosen')
$(btn).addClass('chosen');
textarea.removeClass('hide')
title.removeClass('hide')
/* textarea.val(btn.desc)
textarea[0].currentBtn = btn */
this.imgDescBtnChose(btn)
})
btn.desc = desc || ''
}
Hotpoint.prototype.imgDescBtnChose = function(btn){
var textarea = this.hotpointDetail.find('li[name="photo"] textarea');
textarea[0].currentBtn = btn
textarea.val(btn ? btn.desc : '');
}
//当前处于的状态,比如是否是添加热点的状态
/* Hotpoint.prototype.state = function(that, Hot) {
if (g_HotStatus === "add") {
//console.log(Hot)
this.addHot(that, Hot, (hot)=>{
this.addHotList(hot);
} );
}
} */
Hotpoint.prototype.updateNumDisplay = function() {
this.spotList.find("i").text(this.spotList.find("ul li").length);
}
//删除热点
Hotpoint.prototype.removeHot = function(hot ) {
//hot.dispose();
hot.parent.remove(hot)
delete player.model.hots[hot.sid]
hot.$li.remove();
this.updateNumDisplay()
}
//添加热点模型
Hotpoint.prototype.addHot = function(that) {
if (!player.intersect || !g_HotStatus) return;// 没有正确的热点位置, return
var sid = getRandomSid()
var s = g_HotStatus == 'shine' ? Hot.getDefaulScale() : 1
var hot = new Hot({
sid,
texType : g_HotStatus,
position : player.intersect.point.clone() ,
rotation : [0,0,0],
scale: new THREE.Vector3(s,s,0.02),
actionType : CloneObject(settings.hotClickEvent[g_HotStatus]),
titlePos: this.latestTitlePos,
titleShowType: this.latestTitleShowType,
});
hot.photoHasRequestLoad = hot.modelHasRequestLoad = true;//防止requestDownload
player.model.hots[sid] = hot;
hot.hasRequestLoad = true
hot.isNew = true
if (player.getMouseDirection().angleTo(player.intersect.face.normal) < Math.PI / 2) {
hot.lookAt(player.intersect.face.normal.clone().negate().add(player.intersect.point));
hot.position.add(player.intersect.face.normal.clone().negate().multiplyScalar(0.01)) //avoid mesh crash with chunks 模型的精度可能和floorplan的不一样,所以chunk即使材质经过处理还是会闪烁但是wallmesh不会
} else {
hot.lookAt(player.intersect.face.normal.clone().add(player.intersect.point));
hot.position.add(player.intersect.face.normal.clone().multiplyScalar(0.01))
}
g_HotStatus = false;
player.mouseCouldBeClickToMove = false;
//$("#player").css("cursor", "");
CursorDeal.remove('addHot' )
CursorDeal.remove('noIntersect' )
this.addHotList(hot)
this.editHot(hot)
this.updateTransform('position');
this.updateTransform('quaternion');
}
//添加热点列表
Hotpoint.prototype.addHotList = function(hot) {
var li = $("" + /* "" + (++_hotNum) + "
" + */ "" + ( hot.info.title ) + "
" + "确定删除
" + "" + "");
li.hot = hot
hot.$li = li
this.setListLi(hot)
$(".spotList ul").append(li);
li.on("mouseover",()=>{
hot.changeBoxHelperDisplay(true)
})
li.on("mouseout",()=>{
hot.changeBoxHelperDisplay(false)
})
this.updateNumDisplay()
}
Hotpoint.prototype.setListLi = function(hot){ //暂时用文字展示,最好有图标来表示包含gif和模型
var name = '';
if(hot.info.title) name = hot.info.title
else{
if(hot.info.objSrc)name = '包含模型的'
if(hot.texType == 'photo' && hot.info.animateInfo)name+= 'gif'
else name += (hot.texType == 'shine' ? '热点' : hot.texType == 'photo' ? '图片' : '视频' )
}
hot.$li.find(".title").html(name);
hot.$li.find('.icon').attr("type",hot.texType)
hot.$li.attr("title", hot.info.title) //显示没显示完的标题
}
//添加热点模型列表dom
Hotpoint.prototype.inputList = function(text, val) {
var _val = '';
if (arguments[1]) {
_val = 'value=' + val;
}
return '
'
}
//添加热点模型
Hotpoint.prototype.addModel = function() {
var text = this.inputList("请填写模型链接(https开头)");
this.hotpointDetail.find("[name=modelSrc] .add").on('click', function() {
$(this).closest("[name=modelSrc] ").find(".list").append(text)
});
this.hotpointDetail.find("[name=modelSrc] .delete").on('click', function() {
$(this).closest("[name=modelSrc] ").find(".list > div:last").remove();
});
}
//添加网页链接
Hotpoint.prototype.addwebPack = function() {
var text = this.inputList("请填写网页链接", "");
this.hotpointDetail.find("[name=webPage] .add").on('click', function() {
$(this).closest("[name=webPage]").find(".list").append(text)
});
this.hotpointDetail.find("[name=webPage] .delete").on('click', function() {
$(this).closest("[name=webPage]").find(".list > div:last").remove();
});
}
Hotpoint.prototype.editDone = function(){
var hot = this.editSpot
this.editSpot = null;
hot.isNew = false;
transformControls.detach()
this.hotpointDetail.addClass("atRight");
$('#hotpointDetail .shotImg.innerBtn')[0].cameraData = null
this.setCameraBtn(false)
this.imgDescCheckBox.updateChoseAtUI(false)
$('#setPosForPano [name="dis"]').addClass('hide');
}
// 保存热点信息
Hotpoint.prototype.saveHot = function() {
var $layout = $(".edit-loading");
var hotpointDetail = this.hotpointDetail;
var that = this
var hot = this.editSpot
if (hot.texType == "video" && !hot.texMedia ) {
alert("请添加视频")
return;
}else if(hot.texType == 'photo' && !hot.texMedia){
alert("请添加图片")
return;
}
//显示loading
$layout.removeClass('hide');
var args = hot.info//{};
//热点标题
var $title = hotpointDetail.find("[name=info] input");
//热点内容
var $content = hotpointDetail.find("[name=intro] textarea");
//热点图片
var $images = hotpointDetail.find("[name=content] [name=photo] .edit-fun-images a.result");
//热点视频
var $videos = hotpointDetail.find("[name=content] [name=video] .edit-fun-images a.result");
//热点视频的图片
var $thums = hotpointDetail.find("[name=content] [name=video] .edit-fun-images .upload-thum");
//热点模型
var $modules = hotpointDetail.find("[name=content] [name=modelSrc] input");
//热点内嵌网页
var $iframes = hotpointDetail.find("[name=content] [name=webPage] input.text");
//热点音乐
var $miusc = hotpointDetail.find("[name=content] #upload-hotBgm");
var promise = new Promise(function(resolve, reject) {
//获取图片路径
upload($images, 'images', resolve)
}).then(function(imgUrls) {
$layout.removeClass('hide');
args.images = imgUrls
//获取视频路径
return new Promise(function(resolve, reject) {
upload($videos, 'videos', resolve)
}
)
}).then(function(videoUrls) {
$layout.removeClass('hide');
args.video = videoUrls
//获取视频封面路径
return new Promise(function(resolve, reject) {
upload($thums, 'images', resolve)
}
)
}).then(function(thums) {
$layout.removeClass('hide');
args.video = args.video.map(function(video, index) {//整合视频+封面
return {
url: video,
img: thums[index]
}
})
}).then(function() {
//获取热点音乐所有的路径
//console.log($miusc)
$layout.removeClass('hide');
if ($miusc[0].files.length > 0) {
return new Promise(function(resolve) {
upload($miusc, 'miusc', function(res) {
resolve(res[0])
})
})
} else {
return $miusc.attr('data-hotBgm')
}
}).then(function(src) {
if(that.musicBox.hasMusic && !src){
args.backgroundMusic = hot.info.backgroundMusic
args.bgName = hot.info.bgName
}else{
args.backgroundMusic = src
args.bgName = that.musicBox.getName()
}
}).then(function() { //上传所有热点的tex file
var a = $.Deferred();
var doneNum = 0;
var filesNeedSave = [];
var liNeedSave = [], liNeedSave2 = []
$layout.removeClass('hide');
Array.from(that.styleList.listDom.children()).forEach(li=>{
if(li.sameContentSpots.length == 0)return;//没被热点用到就不保存
//li.sameContentSpots.forEach(spot=>spot.styleImg = li._styleImg)//提前同步下 等下就都是线上链接了
li._styleImg.forEach(img=>{
if(img.needSave && !filesNeedSave.includes(img)){
filesNeedSave.push(img)
liNeedSave.includes(li) || liNeedSave.push(li)
}
})
});
[that.photoList, that.videoList].forEach(list=>{
Array.from(list.listDom.children()).forEach(li=>{
if(li.sameContentSpots.length == 0)return;//没被热点用到就不保存
//li.sameContentSpots.forEach(spot=>spot.texMedia.src = li._media.src)//同步下 video不能同步,只能同步src
li._media.needSave && (filesNeedSave.push(li._media), liNeedSave.push(li))
})
})
Array.from(that.modelList.listDom.children()).forEach(li=>{
if(li.sameContentSpots.length == 0)return;//没被热点用到就不保存
li.objObject.needSave && (filesNeedSave.push(li.objObject), liNeedSave2.push(li))
})
if(filesNeedSave.length){
filesNeedSave.forEach(o=>{
uploadFile(o.file, 'hot', function(rs) {
if (rs.code === 0) {
o.needSave = false;
//o.saveURL = rs.data;
o.src = rs.data;
if (++doneNum >= filesNeedSave.length) {
a.resolve();
liNeedSave.forEach(li=>{//将blob更换成线上链接
li.sameContentSpots.forEach((spot)=>{
if(spot.texType == 'shine'){
spot.info.styleImg = li._styleImg.map(img=>img.src)
}else{
spot.info.texSrc = li._media.src
spot.texMedia.src = li._media.src
}
})
})
liNeedSave2.forEach(li=>{//将blob更换成线上链接
li.sameContentSpots.forEach((spot)=>{
spot.info.objSrc = spot.objObject.src = li.objObject.src
})
})
}
} else {
alert("文件上传失败");
a.reject();
}
})
})
return a.promise()
}else{
return a.resolve()
}
}).then(function() {
$layout.removeClass('hide');
//获取热点标题、内容、内嵌网页、模型网页。
args.title = $title.val()
args.content = $content.val()
var iframes = []
for (var i = 0; i < $iframes.length; i++) {
var iframe = $iframes.eq(i).val()
iframe && iframes.push(iframe)
}
args.iframe = iframes
var modules = []
for (var i = 0; i < $modules.length; i++) {
var module = $modules.eq(i).val()
module && modules.push(module)
}
args.model = modules
/* if(!hot.isSprite){
args.quaternion = hot.quaternion.clone()
//hot.quaternion.copy(hot.mesh.quaternion)
}
args.position = hot.position.clone()
//hot.position.copy(hot.mesh.position) */
return args
}).then(function(args) {
hot.info.texType = hot.texType
if(that.ifNeedResetVisi(hot)){
hot.getVisiblePanos();
}
if(hot.texType == 'photo'){//保存时绑定animateInfo到li
let info = that.photoList.findChosenByContent(that.photoList, hot.texMedia);
info.item.animateInfo = CloneObject(hot.info.animateInfo)
}
if(that.actionCheckBox.checked('fastTran')){
hot.info.cameraData = $('#hotpointDetail .shotImg.innerBtn')[0].cameraData //快速跳转方位
}else{
delete hot.info.cameraData
}
hot.info.imagesDesc = Array.from(that.hotpointDetail.find("[name=photo] .list .descBtn")).map(btn=>btn.desc)
//hot.setTitleElem()//更新名称
that.setListLi(hot);
$layout.addClass('hide');
console.log(args);
that.editDone()
})
return promise
}
Hotpoint.prototype.ifNeedResetVisi = function(hot){//修改过贴图或位置,导致这几个数值改变,就要重新计算可见性(会覆盖用户设置)
var need = !ifSame({
hasBox: hot.tempInfo.hasBox,
position: hot.tempInfo.position,
rotation: hot.tempInfo.rotation,
scale: hot.tempInfo.scale,
transformAtPanos: hot.tempInfo.transformAtPanos,
modelBound:hot.tempInfo.modelBound
}, {
hasBox: hot.info.hasBox,
position: hot.info.position,
rotation: hot.info.rotation,
scale: hot.info.scale,
transformAtPanos: hot.info.transformAtPanos,
modelBound:hot.info.modelBound
})
return need
}
Hotpoint.prototype.getSavingInfo = function(){//保存全部
var hots = {} // 热点数据
/* var shineHots = player.model.hotGroup.children.filter(e=>e.texType == 'shine')
var photoHots = player.model.hotGroup.children.filter(e=>e.texType == 'photo')
var videoHots = player.model.hotGroup.children.filter(e=>e.texType == 'video')
shineHots.concat(photoHots).concat(videoHots).forEach((hot,index)=>{ */
//按列表顺序存储
Array.from(this.spotList.find('li.listItem')).forEach((li,index)=>{
var sid = $(li).attr("data-spid");
var hot = player.model.hots[sid]
var hotData = CloneObject(hot.info)
if(hotData.texSrc){
hotData.texSrc = manage.removeSrcPostMark(hotData.texSrc)
}
hotData.position = toPrecision(hot.info.position.toArray(), 3)
hotData.scale = toPrecision(hot.info.scale.toArray(), 3)
hotData.rotation = toPrecision(hot.info.rotation.toArray().slice(0,3), 4)
hotData.order = index
hotData.transformAtPanos = {}
for(let i in hot.info.transformAtPanos){
hotData.transformAtPanos[i] = {
pos : toPrecision(hot.info.transformAtPanos[i].pos.toArray(), 3),
}
/* if(hot.transformAtPanos[i].qua){
hotData.transformAtPanos[i].qua = toPrecision(hot.transformAtPanos[i].qua.toArray(), 5)
} */
}
hotData.version = 'multi'
if(hotData.animateInfo && hotData.animateInfo.cellXcount * hotData.animateInfo.cellYcount - (hotData.animateInfo.voidCount || 0)<=1){
delete hotData.animateInfo
}
hotData.model = hotData.model.length ? hotData.model : ''
hotData.images = hotData.images.length ? hotData.images : ''
hotData.video = hotData.video.length ? hotData.video : ''
hotData.iframe = hotData.iframe.length ? hotData.iframe : ''
hots[hot.sid] = hotData
})
return hots
}
//背景音乐
var EditBGM = function() {
this.mediaUpload = $(".music .mediaUpload");
this.musicBox = musicPlayBoxBind(this.mediaUpload, (file)=>{
uploadMusic(file, (rs, file)=>{
if (rs.code === 0) {
this.musicBox.show(/* this.mediaUpload, */file.name, rs.data)
}else{
this.musicBox.hide()
}
})
}, null)
}
EditBGM.prototype.init = function(data) {
if (!data.backgroundMusic)
return;
this.musicBox.show(/* this.mediaUpload, */ data.bgName || "backgound", data.backgroundMusic);
}
//导览编辑
var EditGuide = function() {
this.$list = $('#guide-list')
//$('#tourItemEdit') = $('#tourItemEdit');
this.targetTourPoint = null;
// fyz 记录当前编辑的导览点
// fyz 导览音乐队列
//this.tourAudio = {};
}
/**
* @author fyz 2019.07.31
* @description 新增参数data2, 表示data2.js中的数据
*/
EditGuide.prototype.snapATourView = function(renew, insideFolder){
var ev = document.createEvent("MouseEvent");
ev.initMouseEvent("snapshotBegin", true, true, document.defaultView, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
g_snapShotWidth = 200;
g_snapShotHeight = 140;
//window.screenSta = 'tour';
// 记录当前哪个功能截屏, 因为导览截屏需要做额外的校对调整, 初始画面截屏不需要
ev.__callback = (imgData, info)=> {
this.uploadGuide(imgData, info, renew, insideFolder)
};
window.dispatchEvent(ev);
}
EditGuide.prototype.init = function(data, data2) {
this.createDom(data, data2);
//this.tourAudio = data2.tourAudio || {};
var that = this;
//点击添加导览
$('.addTour .innerBtn').eq(0).on("click", function () {
this.addFolderDom({name:"区域"+($("#tourList .listItem").length+1) } );//点击增加一段导览
$("#tourList ul")[0].scrollTop = $("#tourList ul")[0].scrollHeight //scroll to bottom
}.bind(this));
$('.addTour .innerBtn').eq(1).on("click", function () {
this.snapATourView()//点击截取视图
$("#tourList ul")[0].scrollTop = $("#tourList ul")[0].scrollHeight
}.bind(this));
$('.snapATourView .innerBtn').on("click", function() {
this.snapATourView(null,true);//folder内点击截取视图
$("#tourItemList ul")[0].scrollTop = $("#tourItemList ul")[0].scrollHeight
}.bind(this));
$('#renewTourBtn').on("click", function() { // 重新截取视图
this.snapATourView(this, !!this.editingFolderLi);
}.bind(this));
// 确认并保存导览信息
$('#tourFolderEdit .tail .submit').on("click", function() {
this.completeFolder();
}.bind(this));
$('#tourItemEdit .tail .submit').on("click", function() {
this.completeItem();
}.bind(this));
//点击导览编辑窗口右上角的关闭按钮
$("#tourItemEdit a.close, #tourItemEdit .tail .cancel").on("click", ()=>{
/* that.targetTourPoint[0].musicSta = true; ///??????????
// 取消操作, 重置状态
that.tourDetail.addClass("atRight"); */
this.cancelItem()
});
$("#tourFolderEdit a.close, #tourFolderEdit .tail .cancel").on("click", ()=>{
/* that.targetTourPoint[0].musicSta = true; ///??????????
// 取消操作, 重置状态
that.tourDetail.addClass("atRight"); */
this.cancelFolder()
});
//导览目录
$("#tourList").on("click", function(e) {
var target = $(e.target);
let folder = searchParent(e.target, { className: 'listItem' }, 7);
if(!folder)return;//可能点到了item
if (target.hasClass("del")) {
e.stopPropagation();
target.siblings(".DelConfirm").addClass("active");
} else {
if (target.hasClass("DelConfirm")) {
e.stopPropagation();
$(folder).remove()
//that.removeFolder(folder);//删除
} else {
if (target.hasClass("title") || target.hasClass("icon")) {
that.editFolder(folder)//编辑
}
}
}
});
//编辑item
$('.tourList ul').on('click', function(e) {
var target = $(e.target);
let itemDom = searchParent(e.target, { className: 'guideItem' }, 7);
if(!itemDom)return;//可能点到了folder
if(searchParent(e.target, { className: 'preview' })){
var choice = confirm("你确定删除吗?");
if (choice) {
var ul = searchParent(e.target, { className: 'tourList' })
target.closest('li').remove();
reIndexTourList(ul)
} else {
return false
}
}else{
that.editItem(itemDom);
}
})
//音乐
this.musicBoxFolder = musicPlayBoxBind($("#tourFolderEdit .mediaUpload"), null, ()=>{
(that.editingFolderLi || that.editingItemLi).tourData.musicInfo = {}//直接删除 不可逆
})
this.musicBoxItem = musicPlayBoxBind($("#tourItemEdit .mediaUpload"), null, ()=>{
(that.editingFolderLi || that.editingItemLi).tourData.musicInfo = {}//直接删除 不可逆
})
this.momentFolderMenuOptions = new MenuOptions({ //链接打开方式切换
dom: $(" #folderTourSwitch ")
})
this.momentMenuOptions = new MenuOptions({ //链接打开方式切换
dom: $(" #tourSwitch_Slice ")
})
this.rotCheckBox = new CheckBox({dom: $('#tourItemEdit [name="rotSwitch"] input') ,
uiCallBack : (checked )=>{
},
callbackWhenChose:(checked )=>{
this.editingItemLi.tourData.dontRot = checked ? 0 : 1
}
})
{
let ui = $('#tourItemEdit [name="rotTime"] input')
let min = parseFloat(ui.attr('min'));
let max = parseFloat(ui.attr('max'));
ui.on("change", function(e) {
var s = THREE.Math.clamp(parseFloat(e.target.value), min, max)
if(isNaN(s))s = ''
e.target.value = s
that.editingItemLi.tourData.rotTime = s
})
}
{////////////////
let ui = $('.toolRight .snapTour [name="rotTime"] input')
let min = parseFloat(ui.attr('min'));
let max = parseFloat(ui.attr('max'));
ui.on("change", function(e) {
var s = THREE.Math.clamp(parseFloat(e.target.value), min, max)
if(isNaN(s))s = ''
e.target.value = s
})
ui.val(DATA.tourRotTime)
}
{
this.scroller = {
tourBlackSpeed : new SlideBar({
root: $('#tourBlackSpeed').eq(0),
value: 100,
min: 10,
max: 1000,
name: "tourBlackSpeed",
unitStr: "%",
onchange: (s)=>{
},
dragEndEvent: function() {
}
}),
tourWalkSpeed : new SlideBar({
root: $('#tourWalkSpeed').eq(0),
value: 100,
min: 10,
max: 1000,
name: "tourWalkSpeed",
unitStr: "%",
onchange: (s)=>{
},
dragEndEvent: function() {
}
})
}
var tourBlackSpeed = window.DATA.tourBlackSpeed;
if(tourBlackSpeed == void 0){
tourBlackSpeed = 100
}
var tourWalkSpeed = window.DATA.tourWalkSpeed;
if(tourWalkSpeed == void 0){
tourWalkSpeed = 100
}
this.scroller.tourBlackSpeed.setValue(tourBlackSpeed, true)
this.scroller.tourWalkSpeed.setValue(tourWalkSpeed, true)
}
}
function reIndexTourList(ul) {
Array.from($(ul).find('li.guideItem')).forEach((li,index)=>{
$(li).find("div:first-child span").text(index + 1);
})
}
EditGuide.prototype.addFolderDom = function( tourData){
var $folder = $("" + "" + "" + (tourData.name || "") + "
" + "确定删除
" + "" + "");
$folder[0].tourItemDoms = [] //记录所有item的li dom
$folder[0].tourData = tourData //注: data中的locations不会更新,保存时直接读取li
$("#tourList ul").append($folder);
return $folder
}
EditGuide.prototype.getItemDom = function(title, img) {
return '' + '' + '' + '' + title + '' + '' + '
' + '' + '';
}
EditGuide.prototype.createDom = function(data, data2) {
var that = this;
var tourAudio = data2.tourAudio || {};
data.model.images.forEach((Info,index)=>{
if(Info.locations){//是folder
var $folder = this.addFolderDom(Info)
// 音频链接
Info.locations = Info.locations.filter(e=>e)
Info.locations.forEach(function(info, index) {
if (info.thumbnail_signed_src) {
info.thumbnail_signed_src = manage.dealURL(info.thumbnail_signed_src) //旧场景有的少了https://
var $li = $(that.getItemDom( info.name, info.thumbnail_signed_src));
$li[0].tourData = info
$folder[0].tourItemDoms.push($li[0])
}
})
}else{//是散落在外的item
if (Info.thumbnail_signed_src) {
Info.thumbnail_signed_src = manage.dealURL(Info.thumbnail_signed_src)
var $li = $(that.getItemDom(Info.name, Info.thumbnail_signed_src));
$li[0].tourData = Info
// 音频链接
$li[0].tourData.musicInfo = $li[0].tourData.musicInfo || tourAudio[Info.sid] || {}//新的music数据统一写在每个info下
$("#tourList ul").append($li)
}
}
})
reIndexTourList($("#tourList")[0])
}
EditGuide.prototype.editFolder = function(folderDom){
this.editingFolderLi = folderDom;
this.editingFolderLi.tempData = CloneObject(folderDom.tourData);
$("#tourFolderEdit").removeClass('atRight');
$("#tourFolderEdit .tourName input").val( $(folderDom).find('.title').text()||'');
var momentTour = folderDom.tourData.momentTour || "default"
this.momentFolderMenuOptions.updateChoseAtUI({name:momentTour})
folderDom.tourItemDoms.forEach(li=>{
$("#tourItemList>ul").append(li)
})
reIndexTourList($("#tourItemList>ul")[0])
//判断当前点是否有导览音频
var musicInfo = this.editingFolderLi.tourData.musicInfo //audio ? audio.music : null;
if (musicInfo && musicInfo.music) { // 判断改导览点是否已经已有音乐
var musicName = musicInfo.name || '导览音频.mp3' // 获取音频的文件名
this.musicBoxFolder.show( musicName, "//" + musicInfo.music)
} else {
this.musicBoxFolder.hide()
}
}
EditGuide.prototype.editItem = function(li) {
this.editingItemLi = li
this.editingItemLi.tempData = CloneObject(li.tourData);
// 记录当前编辑的导览点
var that = this;
$('#tourItemEdit').removeClass('atRight');
$('#tourItemEdit .tourName input').val( $(li).find('.guide-name').text() );
$('#tourItemEdit [name="rotTime"] input').val(parseFloat(li.tourData.rotTime))
var momentTour = li.tourData.momentTour || "default"
/* $("#tourSwitch_Slice li").removeClass('chosen')
$("#tourSwitch_Slice li[index="+ momentTour +"]").addClass('chosen'); */
this.momentMenuOptions.updateChoseAtUI({name:momentTour})
this.rotCheckBox.updateChoseAtUI(!li.tourData.dontRot)
var metadata = JSON.parse(li.tourData.metadata);
if(metadata.scan_id != 'outside'){
var pano = player.model.panos.index[metadata.scan_id]
if(pano){
var q = new THREE.Quaternion().copy(metadata.camera_quaternion);
player.flyToPano({
pano: pano,
quaternion: q,
zoomLevel: metadata.zoom
})
}
}
if(!this.editingFolderLi){//在外的item, 可以上传音乐
$('#tourItemEdit .mediaUpload').removeClass('hide')
var musicInfo = li.tourData.musicInfo //audio ? audio.music : null;
if (musicInfo && musicInfo.music) { // 判断改导览点是否已经已有音乐
var musicName = musicInfo.name || '导览音频.mp3' // 获取音频的文件名
this.musicBoxItem.show( musicName, "//" + musicInfo.music)
} else {
this.musicBoxItem.hide()
}
}else{
$('#tourItemEdit .mediaUpload').addClass('hide')
}
}
EditGuide.prototype.completeFolder = function(){//点击完成
var tourName = $('#tourFolderEdit .tourName input').val() //|| this.targetTourPoint.context.innerText;
$(this.editingFolderLi).find(".title").text(tourName)
//this.editingFolderLi.tourData.momentTour = $("#folderTourSwitch input").is(':checked') ? "black" : 'walk'
var momentTour = this.momentFolderMenuOptions.getSelectName()//$("#folderTourSwitch li.chosen").attr("index");
this.editingFolderLi.tourData.momentTour = momentTour != 'default' ? momentTour : null;
this.editingFolderLi.tourData.name = tourName
this.editingFolderLi.tourItemDoms = Array.from($('#tourItemList ul li'));
var done = ()=>{
//$("#tourFolderEdit .mediaUpload").find("input").val(''); // 清空 文件
this.musicBoxFolder.hide()// 清空 文件
this.editingFolderLi = null
$("#tourFolderEdit").addClass('atRight');
$(".edit-loading").addClass('hide');
$("#tourItemList>ul").html('')
}
//save导览音乐
var musicFile = this.musicBoxFolder.getFile()
if (musicFile) { //有input文件
$(".edit-loading").removeClass('hide');
var musicName = this.musicBoxFolder.getName()
new Promise( (resolve, reject)=> {
uploadMusic(musicFile, function(res) {
resolve(res.data);
})
} ).then( (src)=>{
$(".edit-loading").removeClass('hide'); //上传完继续显示loading
var audio = new Audio();
audio.src = src;
audio.onloadedmetadata = ()=>{
var srcArr = src.split('/'); // 对返回的src进行处理, 去掉前面域名, 尽量避免修改main.js
srcArr[0] = '';
src = srcArr.join('/');
this.editingFolderLi.tourData.musicInfo = {
"name": musicName,
"music": '/' + src,
"time": Math.round(audio.duration * 1000 + 1000)
}
done()
}
})
}else done()
}
EditGuide.prototype.completeItem = function() {//点击完成
var done = ()=>{
this.musicBoxItem.hide()// 清空 文件
this.editingItemLi = null
$("#tourItemEdit").addClass('atRight');
$(".edit-loading").addClass('hide');
}
var tourName = $('#tourItemEdit .tourName input').val()
$(this.editingItemLi).find('.guide-name').text(tourName)
var momentTour = this.momentMenuOptions.getSelectName()
this.editingItemLi.tourData.momentTour = momentTour != 'default' ? momentTour : null;
this.editingItemLi.tourData.name = tourName
//save导览音乐
var musicFile = this.musicBoxItem.getFile()
if (!this.editingFolderLi && musicFile) { //有input文件
$(".edit-loading").removeClass('hide');
var musicName = this.musicBoxItem.getName() //$('#tourItemEdit .mediaUpload .title').text();
new Promise( (resolve, reject)=>{
uploadMusic(musicFile, function(res) {
resolve(res.data);
})
} ).then( (src)=>{
$(".edit-loading").removeClass('hide'); //上传完继续显示loading
var audio = new Audio();
audio.src = src;
audio.onloadedmetadata = ()=>{
var srcArr = src.split('/'); // 对返回的src进行处理, 去掉前面域名, 尽量避免修改main.js
srcArr[0] = '';
src = srcArr.join('/');
this.editingItemLi.tourData.musicInfo = {
"name": musicName,
"music": '/' + src,
"time": Math.round(audio.duration * 1000 + 1000)
}
done()
}
})
}else done()
}
EditGuide.prototype.cancelFolder = function(){//放弃编辑
this.musicBoxFolder.hide()// 清空 文件
this.editingFolderLi.tourData = this.editingFolderLi.tempData;//还原
this.editingFolderLi.tourItemDoms.forEach((e,i)=>{
e.tourData = this.editingFolderLi.tourData.locations[i]
$(e).find('.guide-name').text(e.tourData.name)
$(e).find('#tourBg')[0].style.backgroundImage = 'url(' + e.tourData.thumbnail_signed_src + ')';
})
this.editingFolderLi = null
$("#tourFolderEdit").addClass('atRight');
$("#tourItemList>ul").html('')
}
EditGuide.prototype.cancelItem = function(){//放弃编辑
this.musicBoxItem.hide()// 清空 文件
this.editingItemLi.tourData = this.editingItemLi.tempData;//还原
$(this.editingItemLi).find('#tourBg')[0].style.backgroundImage = 'url(' + this.editingItemLi.tourData.thumbnail_signed_src + ')';
this.editingItemLi = null
$("#tourItemEdit").addClass('atRight');
}
/**
* @author fyz 2019.07.31
* @description uploadGuide方法新增参数renew状态码, 表示是否重新录制当前导览, 新增targetTourPoint, 记录当前的导览点元素
*/
EditGuide.prototype.uploadGuide = function(urlData, guide, renew, insideFolder) {
var that = this;
uploadImg(urlData, function(rs) {
if (rs.code === 0) {
//var editGuide = new EditGuide();
var sid = rs.data.substring(rs.data.lastIndexOf('/') + 1, rs.data.lastIndexOf('.'));
var thumbnail_signed_src = rs.data;
var args = JSON.parse("{" + guide + "}");
args.sid = sid;
args.name = sid;
args.thumbnail_signed_src = thumbnail_signed_src;
args.metadata = JSON.stringify({
camera_mode: args.metadata.camera_mode,
camera_position: {
x: args.metadata.camera_position[0],
y: args.metadata.camera_position[1],
z: args.metadata.camera_position[2]
},
camera_quaternion: {
x: args.metadata.camera_quaternion[0],
y: args.metadata.camera_quaternion[1],
z: args.metadata.camera_quaternion[2],
w: args.metadata.camera_quaternion[3]
},
ortho_zoom: args.metadata.ortho_zoom,
scan_id: args.metadata.scan_id || "outside",
//这个"outside"不能随便改成别的
/* final_angle: 110,
is_ortho: false, */
zoom: args.metadata.zoom // fyz zoom是内部计算的zoomLevel, 乘以系数1.06才是实际缩放倍数
})
if (renew ) { // 重新录制导览
// 更新数据
if(!insideFolder){
args.musicInfo = that.editingItemLi.tourData.musicInfo;
}
args.name = that.editingItemLi.tourData.name
$(that.editingItemLi).find('#tourBg')[0].style.backgroundImage = 'url(' + args.thumbnail_signed_src + ')';
that.editingItemLi.tourData = args;
} else {
var $li = $(that.getItemDom(args.name, args.thumbnail_signed_src));
$li[0].tourData = args;
var $ul = insideFolder ? $("#tourItemList>ul") : $("#tourList>ul")
$ul.append($li);
reIndexTourList($ul[0])
}
}
},'tour.jpg');
}
EditGuide.prototype.getSavingInfo = function(){
var data = []
Array.from($("#tourList ul li")).forEach(dom=>{
if(dom.classList.contains("guideItem")){//item
//dom.tourData.name = $(dom).find('.guide-name').text()
data.push(dom.tourData)
}else{//folder
var dataFolder = dom.tourData;
//dataFolder.name = $(dom).find('.title').text()
dataFolder.locations = dom.tourItemDoms.map(li => li.tourData )
data.push(dataFolder)
}
})
return data
}
/* -- 以下是一些公用的方法 -- */
//限制大小
var restrictedSize = function(file, _size) {
//限制大小不大于8m
var fileSize = 0;
var isIE = /msie/i.test(navigator.userAgent) && !window.opera;
if (isIE && !file) {
var fileSystem = new ActiveXObject("Scripting.FileSystemObject");
var _file = fileSystem.GetFile(filepath);
fileSize = _file.Size;
} else {
fileSize = file.size;
}
var size = fileSize / 1024;
var RSize = _size * 1024;
if (size > RSize) {
alert("文件不能大于" + _size + "M");
return false;
}
if (size <= 0) {
alert("文件大小不能为0M!");
return false;
}
return true
}
//上传音乐
var uploadMusic = function(file, callback) {
uploadFile(file, 'audio', callback);
}
$(".toolRight .music .itemTitle span").text(`背景音乐 (<${_musicMaxWeight}M)`)
//上传图片
function uploadImg(urlData, callback, fileName) {
//console.log('urlData',urlData);
var bytes = window.atob(urlData.split(',')[1]);
//去掉url的头,并转换为byte
//处理异常,将ascii码小于0的转换为大于0
var ab = new ArrayBuffer(bytes.length);
var ia = new Uint8Array(ab);
for (var i = 0; i < bytes.length; i++) {
ia[i] = bytes.charCodeAt(i);
}
var blob = new Blob([ab],{
type: 'image/jpeg',
});
uploadFile(blob, 'hot/images', callback, fileName);
}
//上传文件
function uploadFile(file, type, callback, fileName) {
$(".edit-loading").removeClass("hide");
var formData = new FormData()
formData.append('name', number)
formData.append('dir', type)
formData.append('random', true)
//formData.append('file', file)
formData.append("file", file, fileName);
let url = cmp ? ('/api/scene/upload/' + number) : ('/manage/scene/upload/' + number)
$.ajax({
url: ceshi + url,
data: formData,
headers: {
token: token
},
dataType: 'json',
type: 'POST',
cache: false,
//上传文件无需缓存
processData: false,
//用于对data参数进行序列化处理 这里必须false
contentType: false,
//必须
success: function(rs) {
if(rs.code === 0){
callback(rs, file);
$(".edit-loading").addClass("hide");
}else if (rs.code === 5001) {
alert('请重新登录')
localStorage.dcj_token = ''
location.reload()
}else{
alert(`uploadFile (url:${url}) code : ${rs.code} \n${rs.msg}`)
}
}
})
}
function _animate(prevRect, target) {
var ms = 300;
if (ms) {
var currentRect = target.getBoundingClientRect();
if (prevRect.nodeType === 1) {
prevRect = prevRect.getBoundingClientRect();
}
_css(target, 'transition', 'none');
_css(target, 'transform', 'translate3d(' + (prevRect.left - currentRect.left) + 'px,' + (prevRect.top - currentRect.top) + 'px,0)');
target.offsetWidth;
// 触发重绘
//放在timeout里面也可以
// setTimeout(function() {
// _css(target, 'transition', 'all ' + ms + 'ms');
// _css(target, 'transform', 'translate3d(0,0,0)');
// }, 0);
_css(target, 'transition', 'all ' + ms + 'ms');
_css(target, 'transform', 'translate3d(0,0,0)');
clearTimeout(target.animated);
target.animated = setTimeout(function() {
_css(target, 'transition', '');
_css(target, 'transform', '');
target.animated = false;
}, ms);
}
}
//给元素添加style
function _css(el, prop, val) {
var style = el && el.style;
if (style) {
if (val === void 0) {
if (document.defaultView && document.defaultView.getComputedStyle) {
val = document.defaultView.getComputedStyle(el, '');
} else if (el.currentStyle) {
val = el.currentStyle;
}
return prop === void 0 ? val : val[prop];
} else {
if (!(prop in style)) {
prop = '-webkit-' + prop;
}
style[prop] = val + (typeof val === 'string' ? '' : 'px');
}
}
}
function upload($files, type, cb) {
var length = $files.length
var rcount = 0
var result = []
Array.from($files).forEach(function(dFile, index) {
//a 标签的success 是用来判断是否是已经上传过的文件
//attr-thum 属性是视频的图片
//videoURL 是判断是否有视频
var $file = $(dFile)
var $image = type == 'videos' ? $file.find('img.play-video') : $file.find('img')
if ($file.hasClass('success')) {//已经上传过,有链接
if ($file.attr('attr-thum')) {//视频的封面
result[index] = $file.attr('attr-thum')
} else if ($image.attr('videoURL')) {//视频
result[index] = $image.attr('videoURL')
} else {
result[index] = $image.attr('src')
}
return success(++rcount);
} else {
switch ($file[0].localName) {
case "input":
dFile = $file[0]
break;
case "span"://封面
dFile = $file.find('input')[0];
break;
case "a"://重传的图or视频
dFile = {files:[$file[0].file]}
//dFile = $file.find('input')[0];
break;
default:
dFile = $file.closest("li").find('.upload input')[0];
break;
}
// dFile = $file[0].localName === "input" ? $file[0] : $file[0].localName === "span" ? $file.find('input')[0] : $file.closest("li").find('.upload input')[0];
}
var file = (dFile.files && dFile.files[0]) || '';
if (!file)
return success(++rcount);
uploadFile(file, 'hot/' + type, function(rs) {
//似乎所有图保存路径都是这个hot/前缀。图地址 :"场景id/edit/重新生成的文件名.原后缀", 展示页面也是。
if (rs.code === 0) {
result[index] = rs.data
}
;success(++rcount);
})
})
//判断当前队列元素是否处理成功
function success() {
if (rcount === length) {
cb(result)
}
}
success()
}
function getIndex(el) {
let index = 0;
if (!el || !el.parentNode) {
return -1;
}
while (el && (el = el.previousElementSibling)) {
index++;
}
return index;
}
dataURLtoBlob = function(dataurl) {
//将base64转换blob
var arr = dataurl.split(',')
, mime = arr[0].match(/:(.*?);/)[1]
, bstr = atob(arr[1])
, n = bstr.length
, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr],{
type: mime
});
}
;
//=========================
var eachMaxWeights = {
//大小限制
"photo": 10,
"video": 1000,//50, expand size for overlayVideo
//20,
"audio": 10, //5
"model": 5
}
var supportTypes = {
//支持后缀
"photo": ["jpg", "png", "jpeg", "bmp", "gif"],
"audio": ["mp3", "aac", "ogg", "wav"/* , "m4a" */],
"video": ["mp4", "mov" ,"webm",/* "rmvb", "wmv" */],//ios:mov
'model':["obj"]
}
function getExt(name) {
//后缀
if (name.indexOf('.') > -1) {
var a = name.split(".");
return a.pop();
} else {
return '';
}
}
function detectType(fileName) {
//检测文件后缀类型
console.log("名:" + fileName)
var ext = getExt(fileName);
console.log("后缀:" + ext)
//不一定所有浏览器都可以
var type;
//仅能根据后缀判断类型,尽管后缀可能被修改。 其他方法如file.type和base64开头的字符串均是根据后缀。
for (var i in supportTypes) {
if (supportTypes[i].indexOf(ext.toLowerCase()) > -1) {
type = i;
break;
}
}
if (type) {
return type;
} else {
return false;
}
}
//手机上的相片会不会太大?
var detectWeights = function(file, type) {
//检测大小
var size = file.size / 1024 / 1024;
console.log("weight" + size)
var over;
if (size > eachMaxWeights[type]) {
over = Math.ceil(size * 100) / 100;
}
return over;
}
var exitUpload = function(input) {
$('.waiting').removeClass('showloading');
input.value = "";
}
var inputMedia = function(options, type, e) {
var input = e.target;
if (!window.FileReader) {
alert('您的浏览器不支持上传文件');
exitUpload(input);
return;
} else if (e.target.files.length === 0) {
/* exitUpload(input); */
return;
}
$('.waiting').addClass('showloading');
var file = e.target.files[0];
var elemType = type;
var inputType = detectType(file.name);
var chType = {
"photo": '图片',
"video": '视频',
"audio": '音乐',
'model': '模型'
}
var overWeight = detectWeights(file, inputType);
if (elemType) {
//有指定其中一种类型
if (inputType != elemType) {
alert("您选择的不是浏览器支持的" + chType[elemType] + '文件,请重新选择');
exitUpload(e.target);
return;
}
} else {
if (!options.enableTypes.includes(inputType)) {
var text = "";
options.enableTypes.forEach((type,index)=>{
text += ((index != 0 ? " / " : "") + chType[elemType])
}
)
alert("您选择的不是浏览器支持的" + text + '文件,请重新选择');
exitUpload(e.target);
return;
}
}
if (overWeight) {
alert(`文件过大(${overWeight}兆),不能大于${eachMaxWeights[inputType]} 兆`)
exitUpload(e.target);
return;
}
var loadError = function() {
exitUpload(e.target);
alert(`文件出错, 无法加载此${chType[inputType]}文件。 文件可能损坏,或者浏览器不支持,或者后缀与文件不匹配。建议在IE以外的浏览器上传`)
}
deal(type);
function deal(type) {
console.log('开始deal文件')
var reader = new FileReader();
//reader.name = file.name;
if(type == 'model'){
reader.readAsText( file );
}else{
reader.readAsDataURL(file);//readAsDataURL
}//readAsArrayBuffer readAsBinaryString
reader.onerror = function(evt) {
loadError()
}
reader.onload = function(evt) {
if(!evt.target.result){
$('.waiting').removeClass('showloading');
return alert('文件出错,可能文件太大')
}
if (inputType == "model") {
var object = new THREE.OBJLoader().parse( evt.target.result );
options.modelDone(file, object)
$('.waiting').removeClass('showloading');
return;
}
var blob = dataURLtoBlob(evt.target.result);
var blobSrc = window.URL.createObjectURL(blob);
if (inputType == "photo") {
/* EXIF.getData(file, function () {
//获取相片旋转
EXIF.getAllTags(this);
var orient = EXIF.getTag(this, 'Orientation');
var img = new Image();
img.src = evt.target.result;
img.onload = function (e) { //这时img才有宽高,才能赋予texture宽高
var smallerImg = CompressImg(e.target, {
weight: blob.size,
maxWeight: 0.5 * 1024 * 1024,
maxSize: 1480
});
//最大500k
smallerImg.onload = function () {
var f = function (resultImg) {//处理结束回调
options.photoDone(resultImg)
$('.waiting').removeClass('showloading');
}
Rotate(smallerImg, orient, f)
window.URL.revokeObjectURL(blobSrc);
}
}
.bind(this)
img.onerror = loadError;
}); */
var img = new Image();
img.setAttribute("crossOrigin", 'Anonymous')//要在src设置好前解决跨域
img.src = blobSrc;
img.base64Src = evt.target.result;
img.file = file;
img.onload = function(e) {
options.photoDone(img)
$('.waiting').removeClass('showloading');
img.onload = null //防止src重新赋值后又触发
}
} else if (inputType == "video") {
var video = $('')[0]
video.setAttribute("crossOrigin", 'Anonymous')
//要在src设置好前解决跨域
$(video).on('contextmenu', function() {
return false;
});
//禁止右键点击出现选项(尤其是下载选项)
$(video).attr('src', blobSrc);
//华为无法使用blobSrc,否则加载不出来
//$(video).attr('src', evt.target.result);
video.base64Src = evt.target.result;
var hasload = false;
var error = false;
var up = function() {
if (hasload)
return;
hasload = true;
options.videoDone(file, video)
$('.waiting').removeClass('showloading');
}
video.addEventListener('loadeddata', function(e) {
up()
})
//video.onerror = loadError;
video.onerror = function(e) {
console.log('error')
error = true;
loadError();
//将mp4改成mov后缀会error
}
} else if (inputType == "audio") {
//林俊波 new Howl For IE&Safari:
var sound = new Howl({
src: [blobSrc],
format: ["mp3"]
});
// Clear listener after first call.
sound.once('load', function() {
console.log('loaded sound')
sound.unload()
console.log("audio.onloadeddata");
var audio = new Audio;
audio.controls = "controls";
audio.src = blobSrc;
audio.base64Src = evt.target.result;
options.audioDone(file, audio)
$('.waiting').removeClass('showloading');
//}
});
sound.once('loaderror', function() {
loadError.apply(this, arguments)
console.log('loaderror sound')
});
// Fires when the sound finishes playing.
sound.on('end', function() {
console.log('Finished sound');
});
}
}
}
e.target.value = "";
//更改value会触发change
}
.bind(player)
//滑动条控件
var SlideBar = function(o) {
var scope = this;
this.name = o.name;
this.value = o.value;
//初始值
this.min = o.min != void 0 ? o.min : 0;
this.max = this.oriMax = o.max != void 0 ? o.max : 100;
this.noValue = o.noValue;
//是否数值输入
this.precision = o.precision;
//精度 保留几位小数
var div = $(''))
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);
}
this.value = THREE.Math.clamp(this.value, this.min, this.max)
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 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.children[0].showZ = this.mode != 'scale' || transformControls.scaleShowZ
}
}
,
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"))
}) */
transformControls.transformMenuOptions = new MenuOptions({
dom: $(".MenuOptions[name='transform'] "),
uiCallBack : (o)=>{
var mode = o.name == void 0 ? o.$li.attr('index') : o.name
transformControls.transCtlChangeMode(mode)
var hotpointDetail = editTool.hotpoint.hotpointDetail
hotpointDetail.find(" li[name=setPos] button[name=setSpace] ").css('display',mode == 'scale' ? 'none' : 'block')
hotpointDetail.find(" li[name=setPos] button[name=useSuitableRatio] ").css('display',mode == 'scale' ? 'block' : 'none')
hotpointDetail.find(" li[name=setPos] button[name=resetRot] ").css('display',mode == 'rotate' ? 'block' : 'none')
},
callbackWhenChose:(o)=>{
}
})
transformControls.enableScaleZ = ()=>{
if(transformControls.mode == 'scale'){
transformControls.children[0].showZ = true
}
transformControls.scaleShowZ = true
}
transformControls.unableScaleZ = ()=>{
if(transformControls.mode == 'scale'){
transformControls.children[0].showZ = false
}
transformControls.scaleShowZ = false
}
}
//----------------漫游可见性---------------------------------
var VisiSet = {
setPanoVisible: false,
setTagVisible: false,
setPanoLog: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 button").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
}
this.changePanoVisi(true)
},
changePanoVisi:function(state){
var floor = player.model.allFloorsVisible ? 'all' : player.model.currentFloor
if(this.setPanoVisible){
if(floor != 'all' && this.panoVsetting && floor != this.panoVsetting.floor){//如果切换到其他楼,取消选中该pano
this.pauseSetPanoVisible('unsaved')
}
}
player.model.panos.forEach(e=>{
if(!e.footIcon)return
if(state && !e.footIcon.visible && (floor == 'all' || floor == e.floor)){
e.footIcon.visible = true
if (this.setPanoLog)e.addTextSprite(e.id, $('#panoIdColorTex').val(), e.footIcon)
}else if(!state || floor != 'all' && floor != e.floor){
e.footIcon.visible = false
if (this.setPanoLog)e.removeTextSprite()
}
})
},
finishSetPanoLog: function() {
//结束 退出这个设置
if (!this.setPanoLog)
return;
//否则会加多个侦听
this.changePanoVisi(false)
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('')
},
dealPanoLogClick: function(object) {
var id = object.name == '' ? object.parent.name : object.name
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, e.footIcon)
})
}
,
//--------------
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(o={}) {
//保存刚设置过的pano
var change = [];
/* if(o.type == 'autoCompute'){
}else{ */
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 array = [];
for (var i = 0; i < panoArr.length; i++) {
var pano = player.model.panos.index[panoArr[i]]//可能undefined,只是存在在panoListOriData中,因在this.data.sweeps[e.uuid].enabled是false
if(pano){
var index = window.panoListOriData.indexOf(pano.id)
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.reticule.visible = !state;
this.changePanoVisi(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].footIcon.position.clone()
/* .sub(player.model.position) */
var line = LineDraw.createLine([pano.footIcon.position.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].position.clone().setY(player.model.center.y) ) /* panos.index[r].floorPosition.clone() *///不用floorPosition是因为有出现和position的水平位置不一样的点,一般是偏移很远的不可见点,拍摄的bug
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)
}
}
//this.changePanoVisi(true)
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)
}
})
},
resetPanosVisiByModel: function() {//一键计算所有漫游可行 (计算后自动连接,但不保存) 多楼层还没试过
$('.waiting').addClass('showloading');
$('.pinBottom .allFloorBtn').click()//全部楼层显示
let begin = ()=>{
this.pauseSetPanoVisible("unsaved")
var ifBlock = function(panoA, panoB ){
var A = panoA.position.clone();
var B = panoB.position.clone();
return !!convertTool.ifIntersectChunks(A, B, {})
}
player.model.panos.list.forEach(pano1=>{
this.SetOnePanoVisible(pano1)//开始设置pano1
player.model.panos.list.forEach(pano2=>{
if(pano1 == pano2)return
if(pano1.id == '9'&& pano2.id == '0'){
console.log(1)
}
var visiNew = !ifBlock(pano1,pano2)
var visiOld = !!(this.panoVLines[pano2.id] && this.panoVLines[pano2.id].visible)
if(visiNew != visiOld){
//console.log('修改 '+pano1.id+'-'+pano2.id)
this.dealPanoVisible(pano2.id)//修改
}
})
this.pauseSetPanoVisible('unsaved')//修改pano1结束
})
$('.waiting').removeClass('showloading');
manage.showInfo("修改成功,可以点击漫游点查看。点击保存当前设置后生效。")
}
setTimeout(()=>{
if(this.setPanoVisible){
begin()
}
},100)
},
//========热点可见性==============
beginSetTagVisible: function() {
if (this.setTagVisible)
return;
$(".toolTop").addClass("unable")
$("#hotVisible button").addClass("unable")
$("#hotVisible label").removeClass('hide')
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].info.isSprite;
player.model.hots[i].info.isSprite = true;
player.model.hots[i].material_.depthTest = false;
player.model.hots[i].position.copy(player.model.hots[i].info.position);//覆盖transformAtPanos
player.model.hots[i].update(player)
}
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.changePanoVisi(true)
this.createTagVisiLines(tag);
//创线
this.updateFootIconSize()
//更新一下大小,尤其是上次换了中心点然后退出又进入但是镜头没有变化的话
},
saveLastTagVi: function() {
//保存刚设置过的tag
var change = false;
var newVPs = this.tagVTemp[this.tagVsetting.sid] || this.tagVsetting.info.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.changePanoVisi(false)
this.tagVTemp = {};
this.tagVsetting = null;
},
finishSetTagVisible: function() {
if (!this.setTagVisible)
return;
$(".toolTop").removeClass("unable")
$("#hotVisible button").removeClass("unable")
$("#hotVisible label").addClass('hide')
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].info.isSprite = player.model.hots[i]._isSprite;
player.model.hots[i].info.isSprite || player.model.hots[i].rotation.copy(player.model.hots[i].info.rotation)
player.model.hots[i].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].setVisiblePanos(this.tagVTemp[i])
}
this.finishSetTagVisible()
//还是保存完直接结束吧,因为现在热点可视不放在单独的设置页面了
},
createTagVisiLines: function(tag) {
// 热点可见性线条
var panos = player.model.panos;
var visibleList = this.tagVTemp[tag.sid] || tag.info.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.footIcon.position.clone()/* .sub(this.position) */
, tag.info.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];
}
},
//------------
/* resetTagVisiByModel : function(){//自动计算所有热点的可视 当模型修改后所有的热点可视都会重新自动计算(用户的设置将被覆盖)
var visiTags = [];
for(var i in objects.tagManager.tags){
var tag = objects.tagManager.tags[i];
if(tag.state == "videoPanoFlag")continue;
var visiblePanos = tag.getVisiblePanos();
visiTags.push({sid:tag.sid, value:visiblePanos})
}
return visiTags;
},
afterResetTagVisibles : function(visiTags){
visiTags.forEach((info)=>{
objects.tagManager.tags[info.sid].setVisiblePanos(info.value);
})
if(objects.player.mode == "panorama")objects.tagManager.updateVisible("panorama");
},
resetVisiblesByModel : function(){//自动计算所有热点和漫游点的可视
this.resetTagVisiByModel()
} */
}
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++;
}
}
function musicPlayBoxBind($dom, addCallback, delCallback){
var musicBox = {
hasMusic:false,
show: function(/* mediaDom, */name, url){
/* mediaDom = mediaDom || $dom
mediaDom.find(".innerBtn").text("替换");
mediaDom.find(".playBox").removeClass("hide");
mediaDom.find(".title").text(name);
mediaDom.find('a').attr('href', url);
musicBox.hasMusic = true */
$dom.find(".innerBtn").text("替换");
$dom.find(".playBox").removeClass("hide");
$dom.find(".title").text(name);
$dom.find('a').attr('href', url);
musicBox.hasMusic = true
},
addMusic : function(e) {
if(!e.target.files.length) return;
var file = e.target.files[0];
if (!/audio\/\w+/.test(file.type)) {
alert("文件必须为音乐!");
return false;
}
//限制大小不大于8m
if (!restrictedSize(file, _musicMaxWeight)) {
return false
}
//var mediaDom = $(searchParent(e.target, { className: 'mediaUpload' }));
musicBox.show(/* mediaDom, */file.name, URL.createObjectURL(file))
addCallback && addCallback(file)
},
delMusic:function(){//手动点击删除
musicBox.hide()
delCallback && delCallback()
},
hide : function(e) {//清空并隐藏
//var mediaDom = e ? $(searchParent(e.target, { className: 'mediaUpload' })) : $dom
$dom.find('a').attr('href', "");
$dom.find(".playBox").addClass("hide");
$dom.find(".innerBtn").text("上传");
$dom.find("input").val("")//.removeAttr("data-hotbgm");
musicBox.hasMusic = false
},
getSrc:function(){
return this.hasMusic && $dom.find('a').attr('href');
},
getName:function(){
return this.hasMusic && $dom.find(".title").text();
},
getFile:function(){//获取刚上传的文件
return this.hasMusic && $dom.find("input")[0].files[0]
}
}
$dom.find("input").on("change", musicBox.addMusic)
/* $dom.find("input").on("click", function() {
mediaUpload
}); */
//删除音乐
$dom.on("click", ".delete", musicBox.delMusic)
return musicBox;
}
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(o){
this.listDom.children().removeClass('selected')
this.chosenItem && this.chosenItem.addClass("selected")
this.options.selectFun( o)
}
selectFromOutSide(index , o){
if(index == null){
var defaultItem = this.listDom.find('.forbitEdit'); //若存在默认选项
if(defaultItem.length){
index = defaultItem.index()
}
}
this.chosenIndex = index;
this.chosenItem = index == void 0 ? null : this.listDom.children().eq(index)
this.updateSelectDisplay(o)
}
addItem($dom){
this.listDom.prepend($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.chosenItem && this.chosenItem[0] == $dom[0]){
this.selectFromOutSide(null)
//this.chosenItem = this.chosenIndex = null
}
if(this.options.delFun){
this.options.delFun($dom)
}
}
saveTemp(){//编辑热点时保存一份副本
this.temp = Array.from(this.listDom.children()).reverse().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.chosenItem = this.chosenIndex = null
//this.selectFromOutSide(this.chosenIndex)
}
bindEvents(){
this.listTitle.on('click',(e)=>{
e.stopPropagation()
this.listDom.toggleClass('hide')
})
document.addEventListener('click',()=>{
this.listDom.addClass('hide')
})
}
}
class ButtonBase{
constructor(o={}){
this.dom = o.dom
this.uiCallBack = o.uiCallBack
this.callbackWhenChose = o.callbackWhenChose //只有点击选择才会触发
}
}
class MenuOptions extends ButtonBase{
constructor(o={}){
super(o)
this.dom.find("li").on("click", (e)=>{
var $elem = $(e.target);
this.updateChoseAtUI({$li:$elem})
this.callbackWhenChose && this.callbackWhenChose({$li:$elem})
})
}
updateChoseAtUI(o={}){
this.dom.find('li').removeClass("chosen");
if(o.$li){
o.$li.addClass("chosen");
}else{
this.dom.find("li[index="+o.name+"]").addClass("chosen");
}
this.uiCallBack && this.uiCallBack(o)
}
getSelectName(){
return this.dom.find('li.chosen').attr('index')
}
}
class CheckBox extends ButtonBase{
constructor(o={}){
super(o)
this.dom.on("change",(e)=>{
var name = $(e.target).attr('name')
this.uiCallBack && this.uiCallBack(e.target.checked, name)
this.callbackWhenChose && this.callbackWhenChose(e.target.checked, name)
})
}
updateChoseAtUI(checked, name){
var dom
if(name) dom = this.dom.filter('[name='+name+']')[0]
else dom = this.dom[0]
dom.checked = checked //this.dom.prop("checked")
this.uiCallBack && this.uiCallBack(checked, name)
}
checked(name){
var dom
if(name) dom = this.dom.filter('[name='+name+']')[0]
else dom = this.dom[0]
return dom.checked
}
}
function setDraggable(o={}){
let findTarget = (event)=>{
let target;
for(let name of o.dragItemClassName){
let tar = searchParent(event.target, { className: name }, o.maxDepth || 7);
if(tar){
target = tar; break;
}
}
return target
}
let draging = null;
let dragStart = (event)=> {
event.dataTransfer.setData("te", event.target.innerText); //不能使用text,firefox会打开新tab
draging = findTarget(event);
}
let dragOver = (event)=>{
event.preventDefault();
let target = findTarget(event);
// 判断dragover是否发生在LI元素上
if (target && target !== draging ) {
let dragingIndex = $(draging).index()//draging.querySelector('#index');
let targetIndex = $(target).index()//target.querySelector('#index');
var targetRect = target.getBoundingClientRect();
var dragingRect = draging.getBoundingClientRect();
if (target && target.animated) {
return;
}
let ulElem = target.parentNode;
// 寻找到 ul节点
if (getIndex(draging) < getIndex(target)) {
//dragingIndex.innerText = [targetIndex.innerText, targetIndex.innerText = dragingIndex.innerText][0];
// 交换两个节点的序号
if(event.clientYtargetRect.bottom-targetRect.height*0.3)return
ulElem.insertBefore(draging, target);
//dragingIndex.innerText = [targetIndex.innerText, targetIndex.innerText = dragingIndex.innerText][0];
}
_animate(dragingRect, draging);
_animate(targetRect, target);
o.callback && o.callback(o.ul, target)
//var ul = searchParent(event.target, { className: 'tourList' })
//reIndexTourList(ul)
}
}
o.ul.ondragstart = dragStart
o.ul.ondragover = dragOver
}
/* class OnOffSwitch extends CheckBox{
constructor(o={}){
super(o)
}
}
*/
/*
待加功能:
//boxhelper改成粗线
热点可视时改成一样大小
热点可视insight优化
hover到热点时列表滚动到这一项
释放geometry内存 、texture
*/