You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

5896 lines
224 KiB

var Map_QM,
renderFrame = -1,
renderCount=0,
pathCameraState,
stats,
isJUZ = false,
shopTime,
debug = false
//basePath 基础路径 graphPath最佳路径 ftPath 扶梯路径 dtPath 电梯路径
var css_LR =
'color:#000000;height: 16px;font-size: 14px; z-index: 90; text-shadow: 1px -1px 0 #fff, 1px -1px 0 #fff, -1px 1px 0 #fff, 1px 1px 0 #fff; pointer-events:none;'
var typeObj = [
{ ft: 0, type: 0, code: 'ft', name: '扶梯' },
{ upft: 1, type: 1, code: 'upft', name: '上扶梯' },
{ downft: 2, type: 2, code: 'downft', name: '下扶梯' },
{ mys: 3, type: 3, code: 'mys', name: '母婴室' },
{ xsj: 4, type: 4, code: 'xsj', name: '洗手间' },
{ dt: 5, type: 5, code: 'dt', name: '直梯' },
{ hxkj: 6, type: 6, code: 'hxkj', name: '焕醒空间' },
{ fwt: 7, type: 7, code: 'fwt', name: '服务台' },
{ tcc: 8, type: 8, code: 'tcc', name: '停车场' },
{ hhkj: 9, type: 9, code: 'hhkj', name: '焕活空间' },
{ cjr: 10, type: 10, code: 'cjr', name: '无障碍洗手间' },
{ xys: 11, type: 11, code: 'xys', name: '吸烟室' },
{ upft: 12, type: 12, code: 'upft', name: '上扶梯' },
{ downft: 13, type: 13, code: 'downft', name: '下扶梯' },
{ dkbc: 14, type: 14, code: 'dkbc', name: '代客泊车' },
{ tczj: 15, type: 15, code: 'tczj', name: '童车租借' },
{ ysc: 16, type: 16, code: 'ysc', name: '饮水处' },
{ ztg: 17, type: 17, code: 'ztg', name: 'L1自提柜' },
{ thg: 18, type: 18, code: 'thg', name: 'B1自提柜' },
{ cwysd: 19, type: 19, code: 'cwysd', name: '宠物饮水点' },
{ td: 20, type: 20, code: 'td', name: '人行通道' },
{ dit: 21, type: 21, code: 'dit', name: '地铁' },
{ czc: 22, type: 22, code: 'czc', name: '出租车' },
{ atm: 23, type: 23, code: 'atm', name: 'ATM' },
{ jcfw: 24, type: 24, code: 'jcfw', name: '寄存服务' },
{ sjcd: 25, type: 25, code: 'sjcd', name: '手机充电' },
{ bc: 26, type: 26, code: 'bc', name: '泊车' },
{ cjc: 27, type: 27, code: 'cjc', name: '裁剪处' },
{ jtn: 28, type: 28, code: 'jtn', name: '家庭洗手间(男)' },
{ jtv: 29, type: 29, code: 'jtv', name: '家庭洗手间(女)' },
{ ksgj: 30, type: 30, code: 'ksgj', name: '公交' },
{ sjxsn: 31, type: 31, code: 'sjxsn', name: '无障碍洗手间男' },
{ sjxsv: 32, type: 32, code: 'sjxsv', name: '无障碍洗手间女' },
{ tcjf: 33, type: 33, code: 'tcjf', name: '停车缴费' },
{ vip: 34, type: 34, code: 'vip', name: 'VIP' },
{ xsjn: 35, type: 35, code: 'xsjn', name: '男洗手间' },
{ xsjv: 36, type: 36, code: 'xsjv', name: '女洗手间' },
{ yszj: 37, type: 37, code: 'yszj', name: '雨伞租借' },
{ dyj: 38, type: 38, code: 'dyj', name: '打印机' },
{ door: 39, type: 39, code: 'door', name: '出入口' },
{ pq: 40, type: 40, code: 'pq', name: '喷泉' },
{ d1k: 41, type: 41, code: 'd1k', name: '1号出入口' },
{ d2k: 42, type: 42, code: 'd2k', name: '2号出入口' },
{ d3k: 43, type: 43, code: 'd3k', name: '3号出入口' },
{ d4k: 44, type: 44, code: 'd4k', name: '4号出入口' },
{ mjzyf: 45, type: 45, code: 'mjzyf', name: '门急诊药房' },
{ cryc: 46, type: 46, code: 'cryc', name: '出入院处' },
{ rggh: 47, type: 47, code: 'rggh', name: '人工挂号收费处' },
{ zzyl: 48, type: 48, code: 'zzyl', name: '自动饮料贩卖机' },
{ gxly: 49, type: 49, code: 'gxly', name: '共享轮椅' },
{ ysp: 50, type: 50, code: 'ysp', name: '艺术品' },
{ B1up: 51, type: 51, code: 'B1up', name: '' },
{ B1down: 52, type: 52, code: 'B1down', name: '' },
{ B2up: 53, type: 53, code: 'B2up', name: '' },
{ B2down: 54, type: 54, code: 'B2down', name: '' },
{ B3up: 55, type: 55, code: 'B3up', name: '' },
{ B3down: 56, type: 56, code: 'B3down', name: '' },
{ xcgc: 57, type: 57, code: 'xcgc', name: '下沉广场' },
{ tthy: 58, type: 58, code: 'tthy', name: '天台花园' },
{ ybck: 59, type: 59, code: 'ybck', name: '医保窗口' },
{ zzfw: 60, type: 60, code: 'zzfw', name: '自助服务' },
{ gjj: 61, type: 61, code: 'gjj', name: '工具间' },
{ syt1: 62, type: 62, code: 'syt1', name: 'mall收银台' },
{ gwc: 63, type: 63, code: 'gwc', name: '购物车' },
{ ht: 64, type: 64, code: 'ht', name: '花坛' },
{ jrc: 65, type: 65, code: 'jrc', name: '自助加热' },
{ qbc: 66, type: 66, code: 'qbc', name: '自助取冰' },
{ zxc: 67, type: 67, code: 'zxc', name: '自行车停放' },
{ jws: 68, type: 68, code: 'jws', name: '警务室' },
{ etxsj: 69, type: 69, code: 'etxsj', name: '儿童洗手间' },
{ vip_xxq: 70, type: 70, code: 'vip_xxq', name: 'vip休息区' },
{ ab: 71, type: 71, code: 'ab', name: '安保' },
{ abjks: 72, type: 72, code: 'abjks', name: '安保监控室' },
{ bys: 73, type: 73, code: 'bys', name: '播音室' },
{ cpgys: 74, type: 74, code: 'cpgys', name: '裁判更衣室' },
{ gzyld: 75, type: 75, code: 'gzyld', name: '观众医疗点' },
{ hqgys: 76, type: 76, code: 'hqgys', name: '后勤更衣室' },
{ jjs: 77, type: 77, code: 'jjs', name: '急救室' },
{ jw: 78, type: 78, code: 'jw', name: '警卫' },
{ ksj: 79, type: 79, code: 'ksj', name: '开水间' },
{ kt: 80, type: 80, code: 'kt', name: '看台' },
{ qzgysn: 81, type: 81, code: 'qzgysn', name: '亲自更衣(男)' },
{ rsggys: 82, type: 82, code: 'rsggys', name: '热身馆更衣室' },
{ swzl: 83, type: 83, code: 'swzl', name: '失物招领' },
{ tsgbs1: 84, type: 84, code: 'tsgbs1', name: '特殊贵宾室1' },
{ tsgbs2: 85, type: 85, code: 'tsgbs2', name: '特殊贵宾室2' },
{ tsgbs3: 86, type: 86, code: 'tsgbs3', name: '特殊贵宾室3' },
{ wxc: 87, type: 87, code: 'wxc', name: '闻讯处' },
{ lt: 88, type: 88, code: 'lt', name: '楼梯' },
{ yhs: 89, type: 89, code: 'yhs', name: '医护室' },
{ yls: 90, type: 90, code: 'yls', name: '医疗室' },
{ ylz: 91, type: 91, code: 'ylz', name: '医疗站' },
{ ydygys: 92, type: 92, code: 'ydygys', name: '运动员更衣室' },
{ ydygysn: 93, type: 93, code: 'ydygysn', name: '运动员男更衣室' },
{ ydygysv: 94, type: 94, code: 'ydygysv', name: '运动员女更衣室' },
{ zls: 95, type: 95, code: 'zls', name: '诊疗室' },
{ zys: 96, type: 96, code: 'zys', name: '直饮水' },
{ zas: 97, type: 97, code: 'zas', name: '治安室' },
{ xxq: 98, type: 98, code: 'xxq', name: '休息区' },
{ jtxsj: 99, type: 99, code: 'jtxsj', name: '家庭洗手间' },
{ hzs: 100, type: 100, code: 'hzs', name: '化妆室' },
{ brs: 101, type: 101, code: 'brs', name: '哺乳室' },
{ mtl: 102, type: 102, code: 'mtl', name: '摩天轮' },
{ dgnxsj: 103, type: 103, code: 'dgnxsj', name: '多功能洗手间' },
{ wxbxsj: 104, type: 104, code: 'wxbxsj', name: '无性别洗手间' },
{ sjzx: 105, type: 105, code: 'sjzx', name: '设计中心' },
{ dxp: 106, type: 106, code: 'dxp', name: '导向牌' },
{ gydh: 107, type: 107, code: 'gydh', name: '公用电话' },
{ sgq: 108, type: 108, code: 'sgq', name: '石拱桥' },
{ wxw: 109, type: 109, code: 'wxw', name: '无线网' },
{ xmb: 110, type: 110, code: 'xmb', name: '小卖部' },
{ zyzfwz: 111, type: 111, code: 'zyzfwz', name: '志愿者服务站' },
{ ykzx: 112, type: 112, code: 'ykzx', name: '服务中心' },
{ zjyy: 113, type: 113, code: 'zjyy', name: '专家预约处' },
{ yjt: 114, type: 114, code: 'yjt', name: '预检台' },
{ mzjd: 115, type: 115, code: 'mzjd', name: '门诊综合接待室' },
{ hd: 116, type: 116, code: 'hd', name: '活动点' },
{ bsl: 117, type: 117, code: 'bsl', name: '白石龙' }
]
QMUtil = function () {
this.shopServerInfo = 'static/offline/JSON/getMapInfo.json'
this.mapServerInfo = 'static/offline/JSON/getMap.json'
this.beforPath = './'
this.tomUrl = "https://qianmu-iot.1000my.com";
this.options = {
playSpeed: 6, //动画播放速度
collision: true, //是否支持名称的碰撞检测
modelIcon: true, //是否使用模型 true 模型 false 图标
otherPath: [], //人为干预的路线 [{f:"0_5_10",s:"1_5_47",d:500},{f:"1_5_47",s:"0_5_10",d:500}];
bSpace: 5000,
fSpace: 500, //双叠层状态下楼层的间距
maxDis: 1000,
minDis: 60,
navColor: 0xee6a50, //途径店铺颜色
aRadius: 2, //圆角半径 大于2 则店铺box显示圆角
iconName: false, //图标名称是否显示
mapScale: 18, //地图比例尺
pathColor: "#6e95fe", //
pathColor2: "#6e7dfe",
pathStyle: '3D',
shopStyle: 'shopName', //设置box显示名称shopName或编号shopNum
inArea: false, //点击后是否聚焦到店铺
camZoom: 3, //设置我的方向状态地图放大倍数
boxShop: [], //设置box上显示的文字(过滤指),可点击触发onlyShop
deviceAng: false, //地图初始化方向是否使用设备角度
facSize: 20 //设施大小
}
this.lightOptions = {
d_col: '#ffffff',
d_int: 0.2,
s_col: '#fffffa',
g_col: '#ffffff',
a_int: 0.85
}
this.m_zoom = 1.2
this._clock = new THREE.Clock()
this._indexPathFloor = 0 // 遍历途径数据
this.changeDist = { inner: 310, outner: 900 } //室内外切换的极限值, 如果 inner小于minDis 则不支持缩放切换
/**
* isPathState 寻路状态
*/
this.pathStateObj = {
isPathState: false,
isPathPlay: true,
basePath: '',
graphPath: '',
ftPath: '',
dtPath: '',
facAllArr: [],
forShopArr: {},
elevator: null,
straight: null,
elevatorDown: null,
seldtFacNo: '',
seldownftFacNo: '',
selupftFacNo: ''
}
this.timeObj = { timeS: 0, collTime: -1, pathTime: -1 }
this.sceneGap = { cameraX: 0, cameraY: 220, cameraZ: 220, x: -10, y: 0, z: 0, scale: 0.08 } //改变地图位置,大小
this.selectBuild = 0
this.selectFloor = 0
this.deviceObj = {} //angle --- 设备旋转角度 node ---- 设备导航点位 floor --- 设备楼层
this.startObj = {} // 导航起点;
this.overObj = {} //导航结束点
this.buildHeight = 5
this.shopHeight = 30 //店铺高度 控制店铺相关的其它第三方组件高度
//服务icon 英文配置
this.iconEn = { 洗手间: 'Toilets', 停车场: 'Parking', 电梯: 'Lift', 扶梯: 'Escalator', 母婴室: 'Baby care room', 服务台: 'service desk' }
//添加平铺logo {floor:5, logoUrl:"./static/img/ss.png", imgW:395, imgH:376, xaxis:1550, yaxis:-860, site:30}
this.logos = []
/**
* 外立面
* Map_QM.util.initModelArr=[{url:"./static/model/jianfa.gltf",type:"out", scale:0.038, rot:{x:0,y:30,z:0}, site:{x:-20,y:-100,z:20}, colorModel:"gama" }];
*/
this.initModelArr = [] //
/**
* 一直显示不隐藏, 在楼层内显示
*/
this.modelArr = []
this.modelStr = [
//种树
{ key: 'tree', url: 'static/img/model/tree.gltf', colorModel: 'line', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 1, y: 1, z: 1 }, load: false },
{ key: 'tree2', url: 'static/img/model/tree2.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'huatan1', url: 'static/img/model/huatan1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'huatan2', url: 'static/img/model/huatan2.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'penquan2', url: 'static/img/model/penquan2.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche1', url: 'static/img/model/qiche1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche2', url: 'static/img/model/qiche2.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche3', url: 'static/img/model/qiche3.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche4', url: 'static/img/model/qiche4.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche5', url: 'static/img/model/qiche5.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche6', url: 'static/img/model/qiche6.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche7', url: 'static/img/model/qiche7.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche8', url: 'static/img/model/qiche8.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'qiche9', url: 'static/img/model/qiche9.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'jt_up', url: 'static/img/model/jt_up.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'jt_left', url: 'static/img/model/jt_left.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'jt_left_up', url: 'static/img/model/jt_left_up.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'jt_right', url: 'static/img/model/jt_right.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'jt_right_up', url: 'static/img/model/jt_right_up.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'jt_turn', url: 'static/img/model/jt_turn.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'ludeng', url: 'static/img/model/ludeng.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'taiyangsan', url: 'static/img/model/taiyangsan.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'honglvdeng', url: 'static/img/model/honglvdeng.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ 'key': 'park_paly', 'url': 'static/img/model/park_paly.glb', 'colorModel': 'gama', 'rot': { 'x': 1.5708, 'y': 0, 'z': 0 }, 'size': { 'x': 80, 'y': 80, 'z': 80 }, 'load':false},
{
key: 'chongdianzhuang',
url: 'static/img/model/chongdianzhuang.glb',
colorModel: 'gama',
rot: { x: 1.5708, y: 0, z: 0 },
size: { x: 20, y: 20, z: 20 },
load: false
},
{ key: 'IDS_H', url: 'static/img/model/IDS_H.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'IDS_V', url: 'static/img/model/IDS_V.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'xiaofangshuan', url: 'static/img/model/xiaofangshuan.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'tingchechang', url: 'static/img/model/tingchechang.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'chechanglangan', url: 'static/img/model/chechanglangan.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'bangongyi', url: 'static/img/model/bangongyi.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'lvzhi', url: 'static/img/model/lvzhi.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'ren1', url: 'static/img/model/ren1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'ren2', url: 'static/img/model/ren2.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'ren3', url: 'static/img/model/ren3.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'ren4', url: 'static/img/model/ren4.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'ren5', url: 'static/img/model/ren5.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'ren6', url: 'static/img/model/ren6.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'yizi1', url: 'static/img/model/yizi1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false },
{ key: 'gjz1', url: 'static/img/model/gjz1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 }, load: false }
]
this.fbxModels = [] //精灵模型
/**
* 模型弹窗
* { htmlUrl: "<p onclick='Map_QM.goHome()' class='other-pop'>进入商场</p>", x: 55, y: 12, z: 3, click: true, type: "out" }
*/
this.tipArr = [] //模型标签 periphery
/**
* 室内地图标签
* Map_QM.util.labelIconArr([{floor:0,title:'<img src="./static/img/iconInfo/lbl_bl.png" width="70" style="position: absolute; bottom: 0px; transform: translateX(-35px);" alt="" >', click:false, site:{x:0,y:1870,z:10},data:{type:"labelIcon",id:"1",show:"cn"}}]);
*/
this.labelIconArr = []
this.spriteMaterialArr = []
this.lineBasicMaterialArr = []
this.meshMaterialArr = []
this.parkMaterialArr = []
this.shopData = [] //店铺数据
this.iconUrl = []
this.allMap = []
/*** ------------------------------------------------ 参数 API START ------------------------------------------------- */
this.setModelState = function (state = '3d') {
//设置模型显示状态 2d 3d
if (Map_QM) {
Map_QM.changeIconState(state)
}
}
this.exportImg = function () {
let tempSrc = Map_QM.renderer.domElement.toDataURL('image/png')
let a = document.createElement('a')
a.href = tempSrc
a.setAttribute('download', 'floor.png')
a.click()
}
/**
* @api {方法} changePlaySpeed(speed) 改变导航速度
* @apiGroup 地图交互
* @apiDescription 改变导航播放速度
* @apiVersion 2.0.0
*
* @apiParam {int} speed 播放速度(默认 6)
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.util.changePlaySpeed(6)
*
*/
this.changePlaySpeed = function (speed = 6) {
Map_QM.util.options.playSpeed = speed
}
/*** ----------------------------------------------- 参数 API END ----------------------------------------------- **** */
this.Point = function (x = 0, y = 0) {
this.x = x
this.y = y
}
this.WallLine = function (start, end) {
this.start = start //起始点位
this.end = end //结束点位
this.leftParLine //左侧平行线段
this.rightParLine //右侧平行线段
this.leftPoint //左侧平行线交点
this.rightPoint //右侧平行线交点
}
this.assignUVs = function (geometry) {
geometry.computeBoundingBox();
let max = geometry.boundingBox.max,
min = geometry.boundingBox.min;
let offset = new THREE.Vector2(0 - min.x, 0 - min.y);
let range = new THREE.Vector2(max.x - min.x, max.y - min.y);
let addX=1, addY=1;
range.x/range.y < 1 ? (addX = range.x/range.y) : (addY = range.y/range.x)
geometry.faceVertexUvs[0] = [];
for (let face of geometry.faces) {
let v1 = geometry.vertices[face.a],
v2 = geometry.vertices[face.b],
v3 = geometry.vertices[face.c];
if(face.normal.z == 0){ //侧面
if(range.x/range.y >= 1){
let repY = range.y/256 >= 2 ? 256:range.y;
face.materialIndex = Math.abs(face.normal.x) < 0.7 ? 2 : 1;
geometry.faceVertexUvs[0].push(face.materialIndex == 1 ? [
new THREE.Vector2((v1.y + offset.y) / repY, v1.z / 512),
new THREE.Vector2((v2.y + offset.y) / repY, v2.z / 512),
new THREE.Vector2((v3.y + offset.y) / repY, v3.z / 512)
] : [
new THREE.Vector2((v1.x + offset.x) / range.x, v1.z / 64),
new THREE.Vector2((v2.x + offset.x) / range.x, v2.z / 64),
new THREE.Vector2((v3.x + offset.x) / range.x, v3.z / 64)
]);
}else{
face.materialIndex = Math.abs(face.normal.x) < 0.7 ? 1 : 2;
geometry.faceVertexUvs[0].push(face.materialIndex == 1 ? [
new THREE.Vector2((v1.x + offset.x) / range.x, v1.z / 512),
new THREE.Vector2((v2.x + offset.x) / range.x, v2.z / 512),
new THREE.Vector2((v3.x + offset.x) / range.x, v3.z / 512)
] : [
new THREE.Vector2((v1.y + offset.y) / range.y, v1.z / 64),
new THREE.Vector2((v2.y + offset.y) / range.y, v2.z / 64),
new THREE.Vector2((v3.y + offset.y) / range.y, v3.z / 64)
]);
}
}else{ //顶面和底面
face.materialIndex = 0;
geometry.faceVertexUvs[0].push([
new THREE.Vector2((v1.x + offset.x) / range.x*addX, (v1.y + offset.y) / range.y*addY),
new THREE.Vector2((v2.x + offset.x) / range.x*addX, (v2.y + offset.y) / range.y*addY),
new THREE.Vector2((v3.x + offset.x) / range.x*addX, (v3.y + offset.y) / range.y*addY)
]);
}
}
geometry.uvsNeedUpdate = true;
}
this.packUv = function (geometry){
geometry.computeBoundingBox();
let max = geometry.boundingBox.max,
min = geometry.boundingBox.min;
let offset = new THREE.Vector2(0 - min.x, 0 - min.y);
let range = new THREE.Vector2(max.x - min.x, max.y - min.y);
geometry.faceVertexUvs[0] = [];
let allReag = 0;
for(let i=0; i< geometry.faces.length; i+=2){
let v1 = geometry.vertices[geometry.faces[i].a],
v2 = geometry.vertices[geometry.faces[i].b];
if(geometry.faces[i].normal.z == 0){ //侧面
if(Math.abs(geometry.faces[i].normal.x) < 0.7){ //左右
allReag+=Math.abs(v2.x-v1.x);
}else{
allReag+=Math.abs(v2.y-v1.y);
}
}
}
for (let face of geometry.faces) {
let v1 = geometry.vertices[face.a],
v2 = geometry.vertices[face.b],
v3 = geometry.vertices[face.c];
if(face.normal.z == 0){ //侧面
face.materialIndex = 1;
if(Math.abs(face.normal.x) < 0.7){ //前后
geometry.faceVertexUvs[0].push([
new THREE.Vector2((v1.x + offset.x) / allReag, v1.z / 512),
new THREE.Vector2((v2.x + offset.x) / allReag, v2.z / 512),
new THREE.Vector2((v3.x + offset.x) / allReag, v3.z / 512)
])
}else{
geometry.faceVertexUvs[0].push([
new THREE.Vector2((v1.y + offset.y) / allReag, v1.z / 512),
new THREE.Vector2((v2.y + offset.y) / allReag, v2.z / 512),
new THREE.Vector2((v3.y + offset.y) / allReag, v3.z / 512)
])
}
}else{ //顶面和底面
face.materialIndex = 0;
geometry.faceVertexUvs[0].push([
new THREE.Vector2((v1.x + offset.x) / range.x, (v1.y + offset.y) / range.y),
new THREE.Vector2((v2.x + offset.x) / range.x, (v2.y + offset.y) / range.y),
new THREE.Vector2((v3.x + offset.x) / range.x, (v3.y + offset.y) / range.y)
]);
}
}
}
/**
* 检测点是否在多边形区域内
*/
this.checkBoundary = function (p, ptPolygon) {
// 判断边界方法
let nCount = ptPolygon.length
let nCross = 0
for (let i = 0; i < nCount; i++) {
let p1 = ptPolygon[i] //当前节点
let p2 = ptPolygon[(i + 1) % nCount] //下一个节点
// 求解 y=p.y 与 p1p2 的交点
if (p1.y == p2.y)
// p1p2 与 y=p0.y平行
continue
if (p.y < Math.min(p1.y, p2.y))
// 交点在p1p2延长线上
continue
if (p.y >= Math.max(p1.y, p2.y))
// 交点在p1p2延长线上
continue
// 从P发射一条水平射线 求交点的 X 坐标 ------原理: ((p2.y-p1.y)/(p2.x-p1.x))=((y-p1.y)/(x-p1.x))
//直线k值相等 交点y=p.y
let x = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x
if (x > p.x) nCross++ // 只统计单边交点
}
// 单边交点为偶数,点在多边形之外 ---
return nCross % 2 == 1
}
this.requestNoJM = function (params) {
params.method = params.method || 'GET'
let xmlhttp = new XMLHttpRequest()
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
let jsonObject
try {
jsonObject = JSON.parse(xmlhttp.responseText)
} catch (e) {
params.fail()
return
}
params.success(jsonObject)
}
if (xmlhttp.readyState === 4 && (xmlhttp.status === 404 || xmlhttp.status === 405)) {
params.fail()
}
}
xmlhttp.onerror = function (e) {
params.fail()
}
xmlhttp.open(params.method, params.url, true)
//xmlhttp.setRequestHeader('Access-Control-Allow-Origin', '*')
xmlhttp.setRequestHeader('Content-type', 'application/json')
//xmlhttp.setRequestHeader('Access-Control-Allow-Method', 'POST,GET')
xmlhttp.send(params.data)
}
this.timeStamp = function () {
return parseInt(new Date().getTime() / 1000)
}
this.readTextFile = function (file, callback) {
let rawFile = new XMLHttpRequest()
rawFile.overrideMimeType('application/json')
rawFile.open('GET', file, true)
rawFile.onreadystatechange = function () {
if (rawFile.readyState === 4 && rawFile.status == 200) {
try {
let jsonObject = JSON.parse(rawFile.response)
callback(jsonObject)
} catch (e) {
//console.log(e);
}
}
}
rawFile.onerror = function () {
callBack(null)
}
rawFile.send(null)
}
this.blocked = (dom, checkList, cfloor, topAd = 0, leftAd = 0) => {
const { top, left, right, bottom } = dom.getBoundingClientRect()
let corners = [
[left + leftAd, top + topAd],
[right - leftAd, top + topAd],
[left + leftAd, bottom - topAd],
[right - leftAd, bottom - topAd]
]
for (let i = 0; i < corners.length; i++) {
const [x, y] = corners[i]
const raycaster = new THREE.Raycaster()
const p = new THREE.Vector2()
let ele = document.getElementById(options.containerId || 'mapContainer')
p.x = (x / parseInt(ele.clientWidth)) * 2 - 1
p.y = -(y / parseInt(ele.clientHeight)) * 2 + 1
raycaster.setFromCamera(p, Map_QM.camera)
let intersects = raycaster.intersectObjects(checkList)
for (let t = 0; t < intersects.length; t++) {
if (intersects[t].object.userData.order > cfloor) {
return true
}
}
}
return false
}
/**碰撞检测
* 传入A中心点和A的宽、高
* B的中心点和B的宽、高
*/
this.isCollision = function (A, B) {
return A.x < B.x + B.width && A.x + A.width > B.x && A.y < B.y + B.height && A.y + A.height > B.y
}
this.changeParkToString = function (area) {
let areaArr = []
for (let i = 0; i < area.hasLines.length; i++) {
let line = area.hasLines[i]
let array = []
array.push(line.startPoint.x, line.startPoint.y, line.endPoint.x, line.endPoint.y)
areaArr.push(array)
}
return areaArr
}
this.changeAreaToString = function (area) {
let areaArr = []
for (let i = 0; i < area.hasLines.length; i++) {
let line = area.hasLines[i]
let array = []
if (line.isStrLine) {
array.push(line.startPoint.x, line.startPoint.y, line.endPoint.x, line.endPoint.y)
} else {
array.push(line.startPoint.x, line.startPoint.y, line.ctrlPoint1.x, line.ctrlPoint1.y, line.ctrlPoint2.x, line.ctrlPoint2.y, line.endPoint.x, line.endPoint.y)
}
areaArr.push(array)
}
return areaArr
}
this.changeWallToString = function (area) {
let areaArr = []
let points = Map_QM.util.getWallPoints(area.pathPoints, area.thick)
for (let i = 0; i < points.length; i++) {
let array = []
let pend = i == points.length - 1 ? points[0] : points[i + 1]
array.push(points[i].x, points[i].y, pend.x, pend.y)
areaArr.push(array)
}
return areaArr
}
this.QM_Line_Father = function (sPoint, ePoint, ctrlPoint1, ctrlPoint2, isStrLine) {
this.startPoint = sPoint //起始点
this.endPoint = ePoint //结束点
this.ctrlPoint1 = ctrlPoint1
this.ctrlPoint2 = ctrlPoint2
this.isStrLine = isStrLine //是否是直线
}
//根据配置参数转换店铺圆角
this.changeShopLinesToString = function (area) {
let areaStr = []
let lines = []
for (let m = 0; m < area.hasLines.length; m++) {
let sPoint, ePoint, cPoint1, cPoint2
sPoint = new Map_QM.util.Point(area.hasLines[m].startPoint.x, area.hasLines[m].startPoint.y)
ePoint = new Map_QM.util.Point(area.hasLines[m].endPoint.x, area.hasLines[m].endPoint.y)
if (area.hasLines[m].isStrLine) {
cPoint1 = null
cPoint2 = null
} else {
cPoint1 = new Map_QM.util.Point(area.hasLines[m].ctrlPoint1.x, area.hasLines[m].ctrlPoint1.y)
cPoint2 = new Map_QM.util.Point(area.hasLines[m].ctrlPoint2.x, area.hasLines[m].ctrlPoint2.y)
}
let line = new Map_QM.util.QM_Line_Father(sPoint, ePoint, cPoint1, cPoint2, area.hasLines[m].isStrLine)
lines.push(line)
}
for (let i = 0; i < lines.length; i++) {
let line0 = lines[i]
let line1 = i < lines.length - 1 ? lines[i + 1] : lines[0]
if (Map_QM.util.options.aRadius > 2) {
if (
line0.isStrLine &&
line1.isStrLine &&
Math.abs(line0.endPoint.x - line0.startPoint.x) + Math.abs(line0.endPoint.y - line0.startPoint.y) > parseInt(Map_QM.util.options.aRadius) * 2
) {
let x1 = line0.endPoint.x
let y1 = line0.endPoint.y
let x2 = line0.startPoint.x
let y2 = line0.startPoint.y
let x3 = line1.endPoint.x
let y3 = line1.endPoint.y
if (Math.abs((x3 - x1) / (x2 - x1) - (y3 - y1) / (y2 - y1)) < 0.1) {
let yArr = []
yArr.push(line0.startPoint.x, line0.startPoint.y, line0.endPoint.x, line0.endPoint.y)
areaStr.push(yArr)
continue
}
let result = Map_QM.util.getIncircleByLines(x1, y1, x2, y2, x3, y3, Map_QM.util.options.aRadius)
let bezierResult = Map_QM.util.getBezier(
result.center.x,
result.center.y,
result.tangencyPoints[0].x,
result.tangencyPoints[0].y,
result.tangencyPoints[1].x,
result.tangencyPoints[1].y,
x1,
y1,
Map_QM.util.options.aRadius
)
if (i > 0) {
let ctrlPoint1,
ctrlPoint2,
array = []
ctrlPoint1 = ctrlPoint2 = new Map_QM.util.Point(
((bezierResult[0].x - line0.startPoint.x) / 2 + line0.startPoint.x) >> 0,
((bezierResult[0].y - line0.startPoint.y) / 2 + line0.startPoint.y) >> 0
) //控制点
array.push(line0.startPoint.x, line0.startPoint.y, ctrlPoint1.x, ctrlPoint1.y, ctrlPoint2.x, ctrlPoint2.y, bezierResult[0].x, bezierResult[0].y)
areaStr.push(array)
} else {
lines[0].endPoint.x = bezierResult[0].x
lines[0].endPoint.y = bezierResult[0].y
}
let arr = []
arr.push(bezierResult[0].x, bezierResult[0].y, bezierResult[1].x, bezierResult[1].y, bezierResult[2].x, bezierResult[2].y, bezierResult[3].x, bezierResult[3].y)
areaStr.push(arr)
line1.startPoint.x = bezierResult[3].x
line1.startPoint.y = bezierResult[3].y
} else {
/////////////////////////////
if (i != 0) {
let pArr = []
if (line0.isStrLine) {
pArr.push(line0.startPoint.x, line0.startPoint.y, line0.endPoint.x, line0.endPoint.y)
} else {
pArr.push(
line0.startPoint.x,
line0.startPoint.y,
line0.ctrlPoint1.x,
line0.ctrlPoint1.y,
line0.ctrlPoint2.x,
line0.ctrlPoint2.y,
line0.endPoint.x,
line0.endPoint.y
)
}
areaStr.push(pArr)
}
}
if (i == lines.length - 1) {
let ocPoint1,
ocPoint2,
oArr = []
if (line1.isStrLine) {
oArr.push(line1.startPoint.x, line1.startPoint.y, line1.endPoint.x, line1.endPoint.y)
} else {
ocPoint1 = new Map_QM.util.Point(line1.ctrlPoint1.x, line1.ctrlPoint1.y)
ocPoint2 = new Map_QM.util.Point(line1.ctrlPoint2.x, line1.ctrlPoint2.y)
oArr.push(line1.startPoint.x, line1.startPoint.y, ocPoint1.x, ocPoint1.y, ocPoint2.x, ocPoint2.y, line1.endPoint.x, line1.endPoint.y)
}
areaStr.push(oArr)
}
} else {
let yArr = []
if (line0.isStrLine) {
yArr.push(line0.startPoint.x, line0.startPoint.y, line0.endPoint.x, line0.endPoint.y)
} else {
yArr.push(
line0.startPoint.x,
line0.startPoint.y,
line0.ctrlPoint1.x,
line0.ctrlPoint1.y,
line0.ctrlPoint2.x,
line0.ctrlPoint2.y,
line0.endPoint.x,
line0.endPoint.y
)
}
areaStr.push(yArr)
}
}
return areaStr
}
//根据圆心、两个切点、切点相交线顶点和半径 计算三次贝塞尔曲线的控制点
this.getBezier = function (x1, y1, x2, y2, x3, y3, x4, y4, radius) {
//切线向量A
var vectorAx = x2 - x1
var vectorAy = y2 - y1
//切线向量B
var vectorBx = x3 - x1
var vectorBy = y3 - y1
//计算切点和圆形组成相交线的夹角
var angle = Math.acos(
(vectorAx * vectorBx + vectorAy * vectorBy) / (Math.sqrt(vectorAx * vectorAx + vectorAy * vectorAy) * Math.sqrt(vectorBx * vectorBx + vectorBy * vectorBy))
)
//计算切点到控制点的距离
var tempDistence = (4 / 3) * radius * Math.tan(angle / 4)
return [
{
x: x2,
y: y2
},
Map_QM.util.getPointFromLine(x2, y2, x4, y4, tempDistence),
Map_QM.util.getPointFromLine(x3, y3, x4, y4, tempDistence),
{
x: x3,
y: y3
}
]
}
//根据半径计算两条线段相切圆的圆心和切点坐标
this.getIncircleByLines = function (x1, y1, x2, y2, x3, y3, radius) {
//向量夹角
let angle = Map_QM.util.getVectorAngle(x2 - x1, y2 - y1, x3 - x1, y3 - y1)
angle = (angle > 180 ? 360 - angle : angle) / 2
//根据夹角计算侧边切点相对于顶点距离
let distance = radius / Math.tan((Math.PI * angle) / 180)
//计算侧边相切点具体坐标
let tangencyPoints = [Map_QM.util.getPointFromLine(x1, y1, x2, y2, distance), Map_QM.util.getPointFromLine(x1, y1, x3, y3, distance)]
let centerX, centerY
let areaSize = (x2 - x1) * (y3 - y1) - (y2 - y1) * (x3 - x1)
//计算圆心坐标
if (areaSize < 0) {
centerX = (tangencyPoints[0].x * (1 / Math.tan((Math.PI * angle) / 180)) + tangencyPoints[0].y - y1) / (1 / Math.tan((Math.PI * angle) / 180))
centerY = (tangencyPoints[0].y * (1 / Math.tan((Math.PI * angle) / 180)) + x1 - tangencyPoints[0].x) / (1 / Math.tan((Math.PI * angle) / 180))
} else {
centerX = (tangencyPoints[1].x * (1 / Math.tan((Math.PI * angle) / 180)) + tangencyPoints[1].y - y1) / (1 / Math.tan((Math.PI * angle) / 180))
centerY = (tangencyPoints[1].y * (1 / Math.tan((Math.PI * angle) / 180)) + x1 - tangencyPoints[1].x) / (1 / Math.tan((Math.PI * angle) / 180))
}
return {
center: {
x: centerX,
y: centerY
},
tangencyPoints: tangencyPoints,
angle: (Math.PI * angle) / 90
}
}
//根据距离计算线段上某一点的具体坐标
this.getPointFromLine = function (startX, startY, endX, endY, distance) {
if (startX == endX)
return {
x: startX,
y: startY < endY ? startY + distance : startY - distance
}
let k = ((startY - endY) * 1.0) / (startX - endX)
let b = startY - k * startX
let A = Math.pow(k, 2) + 1
let B = 2 * ((b - startY) * k - startX)
let C = Math.pow(b - startY, 2) + Math.pow(startX, 2) - Math.pow(distance, 2)
let x1 = (-B + Math.sqrt(Math.pow(B, 2) - 4 * A * C)) / (2 * A)
let x2 = (-B - Math.sqrt(Math.pow(B, 2) - 4 * A * C)) / (2 * A)
let x = 0
if (x1 == x2) x = x1
else if ((startX <= x1 && x1 <= endX) || (endX <= x1 && x1 <= startX)) x = x1
else if ((startX <= x2 && x2 <= endX) || (endX <= x2 && x2 <= startX)) x = x2
let y = k * x + b
return {
x: x,
y: y
}
}
//计算两个向量之间的夹角
this.getVectorAngle = function (x1, y1, x2, y2) {
let epsilon = 1.0e-6
let dist, dot, degree, angle
dist = Math.sqrt(x1 * x1 + y1 * y1)
x1 /= dist
y1 /= dist
dist = Math.sqrt(x2 * x2 + y2 * y2)
x2 /= dist
y2 /= dist
dot = x1 * x2 + y1 * y2
if (Math.abs(dot - 1.0) <= epsilon) angle = 0
else if (Math.abs(dot + 1.0) <= epsilon) angle = Math.PI
else {
angle = Math.acos(dot)
let cross = x1 * y2 - x2 * y1
if (cross < 0) angle = 2 * Math.PI - angle
}
degree = (angle * 180) / Math.PI
return degree
}
//检测区域是否在区域内 true (area2包含area)
this.checkAreaInArea = function (area, area2) {
let ptPolygon = []
for (let i = 0; i < area2.hasLines.length; i++) {
let line = area2.hasLines[i]
let pArr
if (line.isStrLine) {
pArr = Map_QM.util.getPointArrOnLine(line.startPoint, line.endPoint)
} else {
pArr = Map_QM.util.getPointArr(line.startPoint, line.ctrlPoint1, line.ctrlPoint2, line.endPoint, 0.1)
}
ptPolygon.push(...pArr)
}
for (let f = 0; f < area.hasLines.length; f++) {
let line2 = area.hasLines[f]
let sPoint = Map_QM.util.checkBoundary(new Map_QM.util.Point(line2.startPoint.x, line2.startPoint.y), ptPolygon)
let ePoint = Map_QM.util.checkBoundary(new Map_QM.util.Point(line2.endPoint.x, line2.endPoint.y), ptPolygon)
if (!sPoint || !ePoint) {
return false
}
}
return true
}
/**
* 返回取得点的数组
* s1--起点 s2 --终点 s3,s4 --控制点
*/
this.getPointArr = function (s1, s3, s4, s2, sp = 0.01) {
let pArr = []
let sz = [s1, s3, s4, s2]
let p
for (let j = 0; j < 1; j += sp) {
p = Map_QM.util.P_BEZ(j, sz)
pArr.push(p)
}
return pArr
}
this.P_BEZ = function (t, sz) {
//n次
let x_p = 0
let y_p = 0
let n = sz.length
for (let i = 0; i < sz.length; i++) {
let son = Map_QM.util.jie_cheng(n - 1)
let mother = Map_QM.util.jie_cheng(i) * Map_QM.util.jie_cheng(n - 1 - i)
let b = (son / mother) * Math.pow(t, i) * Math.pow(1 - t, n - 1 - i)
x_p += sz[i].x * b
y_p += sz[i].y * b
}
x_p = Number(x_p * 1000) / 1000
y_p = Number(y_p * 1000) / 1000
return new Map_QM.util.Point(x_p, y_p)
}
this.jie_cheng = function (i) {
//阶乘
let n = 1
for (let j = 1; j <= i; j++) {
n *= j
}
return n
}
/**
* 获取线段上的所有点
*/
this.getPointArrOnLine = function (s1, s2) {
let points = []
if (s1.x == s2.x) {
let vy = s1.y < s2.y ? 1 : -1
for (let m = 1; m < Math.abs(s1.y - s2.y); m++) {
let y0 = s1.y + m * vy
let x0 = s1.x
points.push(new Map_QM.util.Point(x0, y0))
}
return points
}
let k = (s1.y - s2.y) / (s1.x - s2.x) // 坐标直线斜率k
let b = s1.y - k * s1.x // 坐标直线b
if (Math.abs(s1.x - s2.x) > Math.abs(s1.y - s2.y)) {
let vx = s1.x < s2.x ? 1 : -1
for (let i = 1; i < Math.abs(s1.x - s2.x); i++) {
let x0 = s1.x + i * vx
let y0 = k * x0 + b
points.push(new Map_QM.util.Point(x0, y0))
}
} else {
let vy = s1.y < s2.y ? 1 : -1
for (let n = 1; n < Math.abs(s1.y - s2.y); n++) {
let y0 = s1.y + n * vy
let x0 = (y0 - b) / k
points.push(new Map_QM.util.Point(x0, y0))
}
}
return points
}
//转换公共设施type值
this.getFacType = function (str) {
for (let i = 0; i < typeObj.length; i++) {
if (typeObj[i].code && typeObj[i].code == str) {
return typeObj[i].type
}
}
}
this.getFacName = function (str) {
for (let i = 0; i < typeObj.length; i++) {
if (typeObj[i].code && typeObj[i].code == str) {
return typeObj[i].name
}
}
}
//店铺排序
this.sortShopByFloor = function (a, b) {
return a.floorOrder < b.floorOrder ? -1 : 1
}
this.sortNode = function (a, b) {
return a.id - b.id
}
////////////////////////////////////////////////////////////////////////////////////////////
this.getWallPoints = function (points, wallWidth) {
if (points.length < 2) {
return new Array()
}
//构建线段列表
let lines = new Array()
for (let index = 0; index < points.length - 1; index++) {
let startPoint = points[index]
let endPoint = points[index + 1]
let line = Map_QM.util.getParallelLine(startPoint, endPoint, wallWidth)
lines.push(line)
}
//生成线段对应的左右两侧平行线
for (let index = 0; index < lines.length - 1; index++) {
let start = lines[index]
let end = lines[index + 1]
if (start.leftParLine != null && start.rightParLine != null && end.leftParLine != null && end.rightParLine != null) {
start.leftPoint = Map_QM.util.getIntersectionByLines(start.leftParLine, end.leftParLine)
start.rightPoint = Map_QM.util.getIntersectionByLines(start.rightParLine, end.rightParLine)
}
}
//循环线段列表 获取墙体所有点位 顺序为 左侧起始点->左侧所有交点->左侧结束点->右侧结束点->右侧所有交点->右侧起始点
let leftPointList = new Array()
let rightPointList = new Array()
for (let index = 0; index < lines.length; index++) {
//第一条线段 记录左右两侧平行线的起点坐标
if (index == 0) {
leftPointList.push(lines[index].leftParLine.start)
rightPointList.push(lines[index].rightParLine.start)
}
//最后一条线段 记录左右两侧平行线的终点坐标
if (index == lines.length - 1) {
leftPointList.push(lines[index].leftParLine.end)
rightPointList.push(lines[index].rightParLine.end)
} else {
//记录线段左右平行线交点坐标
if (!isNaN(lines[index].leftPoint.x) || !isNaN(lines[index].leftPoint.y) || !isNaN(lines[index].rightPoint.x) || !isNaN(lines[index].rightPoint.y)) {
leftPointList.push(lines[index].leftPoint)
rightPointList.push(lines[index].rightPoint)
}
}
}
rightPointList.reverse()
return leftPointList.concat(rightPointList)
}
//生成线段左右两侧的平行线
this.getParallelLine = function (start, end, wallWidth) {
let line = new Map_QM.util.WallLine(start, end)
//计算当前线段的斜率
let gradient = (start.y - end.y) / (start.x - end.x)
//计算垂直线的斜率
let perGradient = -1 / gradient
//获取垂直线上左右两侧 与当前点位相距一定距离的两个定点
let startResult = Map_QM.util.getParallelPoints(perGradient, start, wallWidth)
let endResult = Map_QM.util.getParallelPoints(perGradient, end, wallWidth)
let x1 = startResult[0].x
let y1 = startResult[0].y
let x2 = endResult[0].x
let y2 = endResult[0].y
let x3 = end.x
let y3 = end.y
let x4 = startResult[1].x
let y4 = startResult[1].y
let x5 = endResult[1].x
let y5 = endResult[1].y
let s = (x1 - x3) * (y2 - y3) - (y1 - y3) * (x2 - x3)
//判断点位位于线段的左侧还是右侧
if (s >= 0) {
line.leftParLine = new Map_QM.util.WallLine(new Map_QM.util.Point(x1, y1), new Map_QM.util.Point(x2, y2))
line.rightParLine = new Map_QM.util.WallLine(new Map_QM.util.Point(x4, y4), new Map_QM.util.Point(x5, y5))
} else {
line.leftParLine = new Map_QM.util.WallLine(new Map_QM.util.Point(x4, y4), new Map_QM.util.Point(x5, y5))
line.rightParLine = new Map_QM.util.WallLine(new Map_QM.util.Point(x1, y1), new Map_QM.util.Point(x2, y2))
}
return line
}
// 生成线段起始 和 结束 点位 对应的 两条 与线段垂直的直线 并记录坐标
this.getParallelPoints = function (gradient, point, wallWidth) {
let x, y
//斜率为无穷大时 计算不了垂直线 指定点位
if (gradient == Number.NEGATIVE_INFINITY || gradient == Number.POSITIVE_INFINITY) {
x = point.x
y = point.y + 5
} else {
//不是横线时 根据斜率计算点位
x = point.x + 5
y = gradient * (x - point.x) + point.y
}
return Map_QM.util.pointXY(point, new Map_QM.util.Point(x, y), wallWidth / 2)
}
// 获取点位在直线上的坐标
this.pointXY = function (curPoint, nextPoint, length) {
let result = new Array()
//x值相等 说明是竖线 只需增减y轴坐标
if (curPoint.x == nextPoint.x) {
result.push(new Map_QM.util.Point(curPoint.x, curPoint.y + length))
result.push(new Map_QM.util.Point(curPoint.x, curPoint.y - length))
return result
}
//根据 斜率 和 距离 计算出对应的两个点位
let k = (curPoint.y - nextPoint.y) / (curPoint.x - nextPoint.x)
let b = curPoint.y - k * curPoint.x
let A = Math.pow(k, 2) + 1
let B = 2 * ((b - curPoint.y) * k - curPoint.x)
let C = Math.pow(b - curPoint.y, 2) + Math.pow(curPoint.x, 2) - Math.pow(length, 2)
let x1 = (-B + Math.sqrt(Math.pow(B, 2) - 4 * A * C)) / (2 * A)
let x2 = (-B - Math.sqrt(Math.pow(B, 2) - 4 * A * C)) / (2 * A)
result.push(new Map_QM.util.Point(x1, k * x1 + b))
result.push(new Map_QM.util.Point(x2, k * x2 + b))
return result
}
//计算两条直线的相交点
this.getIntersectionByLines = function (line1, line2) {
//直线斜率
let gradient1 = (line1.end.y - line1.start.y) / (line1.end.x - line1.start.x)
let gradient2 = (line2.end.y - line2.start.y) / (line2.end.x - line2.start.x)
//斜率差值小于一定范围 表示两条线近似平行 因为交点太远 可能超出屏幕 直接取线段中点为交点
if (Math.abs(gradient1 - gradient2) < 0.1) return new Map_QM.util.Point(line1.end.x, line1.end.y)
let x1 = line1.start.x
let y1 = line1.start.y
let x2 = line1.end.x
let y2 = line1.end.y
let x3 = line2.start.x
let y3 = line2.start.y
let x4 = line2.end.x
let y4 = line2.end.y
//计算交点坐标
let x = ((x1 - x2) * (x3 * y4 - x4 * y3) - (x3 - x4) * (x1 * y2 - x2 * y1)) / ((x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4))
let y = ((y1 - y2) * (x3 * y4 - x4 * y3) - (x1 * y2 - x2 * y1) * (y3 - y4)) / ((y1 - y2) * (x3 - x4) - (x1 - x2) * (y3 - y4))
return new Map_QM.util.Point(x, y)
}
/**
* 根据色值获取材质
*/
this.getMeshMaterial = function (color, alphaModle = 0.9) {
let meshMaterial
for (let k = 0; k < Map_QM.util.meshMaterialArr.length; k++) {
let color2 = new THREE.Color(color)
if (Map_QM.util.meshMaterialArr[k].color && Map_QM.util.meshMaterialArr[k].color.equals(color2) && Map_QM.util.meshMaterialArr[k].opacity == alphaModle) {
meshMaterial = Map_QM.util.meshMaterialArr[k]
}
}
if (!meshMaterial) {
meshMaterial = new THREE.MeshPhongMaterial({
color: color,
emissive: 0x000000,
specular: 0x000000,
transparent: true,
side: THREE.DoubleSide,
opacity: alphaModle
})
Map_QM.util.meshMaterialArr.push(meshMaterial)
}
return meshMaterial
}
this.rotateYZ = function (geometry, ry, rz) {
let center = new THREE.Vector3()
geometry.computeBoundingBox()
geometry.boundingBox.getCenter(center)
let x = center.x
let y = center.y
let z = center.z
geometry.center()
geometry.rotateY(ry)
geometry.rotateX(rz)
geometry.translate(x, y, z)
}
}
//////////////////////////////-------------------------------------------配置 UtilFun
/**
* 地图主类,入口 初始化设备点位
*/
MainMap_QM = function (callBack, options) {
this.util = new QMUtil()
this.callBackLoadOver = callBack
this.ele = document.getElementById(options.containerId || 'mapContainer')
this.w = parseInt(this.ele.clientWidth) || parseInt(window.getComputedStyle(this.ele, null).getPropertyValue('width'))
this.h = parseInt(this.ele.clientHeight) || parseInt(window.getComputedStyle(this.ele, null).getPropertyValue('height'))
this.backObj = { code: 200, msg: '加载成功', data: [] }
this.scene = new THREE.Scene()
this.scene.name = 'scene'
this.aspect = this.w / this.h
this.cameraPerspective = new THREE.PerspectiveCamera(45, this.aspect, 10, 10000)
this.cameraPerspective.position.set(this.util.sceneGap.cameraX, this.util.sceneGap.cameraY, this.util.sceneGap.cameraZ) //x 水平 y 垂直旋转 z 展示大小
this.cameraPerspective.lookAt(new THREE.Vector3(0, 0, 0))
this.cameraOrtho = new THREE.OrthographicCamera(-150 * this.aspect, 150 * this.aspect, 150, -150, 10, 10000)
this.cameraOrtho.position.set(this.util.sceneGap.cameraX, this.util.sceneGap.cameraY, this.util.sceneGap.cameraZ)
this.cameraOrtho.lookAt(new THREE.Vector3(0, 0, 0))
this.camera = this.cameraPerspective
//
this.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true, preserveDrawingBuffer: true }) // preserveDrawingBuffer 是否可以截图
//this.renderer.outputEncoding = THREE.sRGBEncoding;
this.renderer.setSize(this.w, this.h)
this.renderer.setPixelRatio(window.devicePixelRatio)
this.renderer.shadowMap.enabled = false
this.ele.appendChild(this.renderer.domElement)
this.labelRenderer = new THREE.CSS2DRenderer()
//弹窗的偏移百分比 或者像素
this.labelRenderer.setSize(this.w, this.h, options.perc_H || '-50%')
this.labelRenderer.domElement.style.position = 'absolute'
this.labelRenderer.domElement.style.top = 0
this.ele.appendChild(this.labelRenderer.domElement)
let light = new THREE.AmbientLight(0xffffff, 0.4)
light.name = 'light'
this.scene.add(light)
this.hemiLight = new THREE.HemisphereLight(this.util.lightOptions.s_col, this.util.lightOptions.g_col, this.util.lightOptions.a_int)
this.hemiLight.name = 'light'
this.hemiLight.position.set(0, 1, 1)
this.scene.add(this.hemiLight)
this.shawLight = new THREE.DirectionalLight(this.util.lightOptions.d_col, this.util.lightOptions.d_int)
this.shawLight.name = 'light'
this.shawLight.position.set(280, 400, -300)
this.scene.add(this.shawLight)
this.mixers = []
this.controls = new THREE.OrbitControls(this.camera, this.ele)
//鼠标控制
//this.controls.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
//this.controls.enabled = true;
this.controls.minZoom = 0.8
this.controls.maxZoom = this.util.options.camZoom
//设置相机距离原点的最远距离
this.controls.minDistance = this.util.options.minDis
//设置相机距离原点的最远距离
this.controls.maxDistance = this.util.options.maxDis
this.controls.minPolarAngle = 0 // 0是为了兼容2D模式
this.controls.maxPolarAngle = Math.PI / 2 - 0.2 // radians
if (debug) {
stats = new Stats()
stats.setMode(1) // 0: fps, 1: ms
stats.domElement.style.position = 'absolute' //绝对坐标
stats.domElement.style.left = '10px' // (0,0)px,左上角
stats.domElement.style.top = '60px'
this.ele.appendChild(stats.domElement)
}
this.ele.addEventListener("wheel", this.disPlayEvent);
this.ele.addEventListener("mouseup", this.disPlayEvent);
this.ele.addEventListener("touchmove", this.mouseMove);
this.ele.addEventListener('touchend',this.mouseUp);
this.ele.addEventListener('click', this.onMouseClickBox) //地图点击
document.addEventListener('resize', this.changeDocmentResize) //窗口变化
this.mapArr = []
this.selectShop
this.selectEle = null //当前使用的电梯
this.overShop //终点店铺
this.shape = new THREE.Shape()
this.shape.moveTo(-10, -10)
this.shape.lineTo(10, -10)
this.shape.lineTo(10, 10)
this.shape.lineTo(-10, 10)
this.dtLineGroup = new THREE.Group()
this.dtLineGroup.name = 'dtLine'
if (document.getElementById('moveFloorBG')) {
document.getElementById('moveFloorBG').style.zIndex = 500;
this.moveFloorbg = new THREE.CSS2DObject(document.getElementById('moveFloorBG'))
this.moveFloorbg.userData.isShow = false;
}
this.mixers = []
this.man_3d=null
this.man_2d=null
this.guide=null
this.sceneGap = new THREE.Group()
this.outModelGap = new THREE.Group() //全局外立面模型
this.scene.add(this.outModelGap)
this.peripheryGap = new THREE.Group() //周边模型
this.scene.add(this.peripheryGap)
this.outObject = new THREE.Object3D()
this.outObject.userData.type = "moveFloor"
this.perObject = new THREE.Object3D()
this.perObject.userData.type = "moveFloor"
this.buildObj = new THREE.Group()
this.qiModel=null //起点
this.qiIcon=null //起点Icon
this.dirIcon=null //我的方向Icon
this.endIcon=null //终点Icon
this.endModel=null
this.forShopArr = [] //途径数据
this.getInstance(options)
}
MainMap_QM.prototype = {
mouseMove:function(){
Map_QM.disPlayEvent()
},
mouseUp:function(){
Map_QM.disPlayEvent()
},
getInstance: function (options) {
this.util.startObj.build = this.util.deviceObj.build = parseInt(options.build) || 0
this.util.startObj.node = this.util.deviceObj.node = parseInt(options.navPoint) || 1
this.util.deviceObj.angle = parseInt(options.angle) || 0
this.util.selectBuild = this.util.deviceObj.build
let _space = this
if (options.mallCode) {
let tim = this.util.timeStamp()
this.util.requestNoJM({
method: "GET",
url: options.url + "/api/info/v1/web/getUploadUrl",
success: (res)=>{
_space.tomUrl = res.data;
this.util.requestNoJM({
method: "GET",
url: _space.tomUrl + "/ar/"+options.mallCode+"/config.json?a="+tim,
success: (res)=>{
_space.util.shopServerInfo = res.shopUrl
_space.util.mapServerInfo = res.mapUrl
_space.initLoadMapFile(options)
},
fail:()=>{
_space.backObj.code = 404
_space.backObj.msg = "地图数据获取失败"
_space.callBackLoadOver(_space.backObj)
_space.callBackLoadOver = null
}
})
},
fail:()=>{
this.util.requestNoJM({
method: "GET",
url: _space.tomUrl + "/ar/"+options.mallCode+"/config.json?a="+tim,
success: (res)=>{
_space.util.shopServerInfo = res.shopUrl
_space.util.mapServerInfo = res.mapUrl
_space.initLoadMapFile(options)
},
fail:()=>{
_space.backObj.code = 404
_space.backObj.msg = "地图数据获取失败"
_space.callBackLoadOver(_space.backObj)
_space.callBackLoadOver = null
}
})
}
})
} else {
if (options.mapData) {
try {
if (options.mapData.mallKey != 'Zeditor') {
_space.util.allMap = JSON.parse(options.mapData.mapData)
} else {
_space.util.allMap = JSON.parse(LZString.decompressFromBase64(options.mapData.mapData))
}
console.log("地图数据更新时间: " + options.mapData.updateTime);
} catch (e) {
console.log(e)
backObj.code = 404
backObj.msg = '地图数据JSON格式错误'
callBack(backObj)
callBack = null
return;
}
_space.util.shopData = options.shopData;
_space.initOptions(options);
} else {
_space.initLoadMapFile(options);
}
}
},
initLoadMapFile:function(options){
_space = this
_space.util.readTextFile(_space.util.mapServerInfo, function (res) {
console.log(res)
if(res){
try {
if(Array.isArray(res.data)){
for(let map of res.data){
if (map.mapKey == "Aeditor") {
_space.util.allMap = JSON.parse(map.mapData);
break;
}
}
}else{
if (res.data.mallKey != "Zeditor") {
_space.util.allMap = JSON.parse(res.data.mapData);
} else {
_space.util.allMap = JSON.parse(LZString.decompressFromBase64(res.data.mapData));
}
}
console.log("地图数据更新时间: " + res.data.updateTime);
} catch (e) {
console.log(e);
_space.backObj.code = 404;
_space.backObj.msg = "地图数据JSON格式错误";
_space.callBackLoadOver(_space.backObj);
_space.callBackLoadOver = null;
return;
}
_space.util.readTextFile(_space.util.shopServerInfo, function (res) {
_space.util.shopData = [];
if(res){
if(res.data.length>4){ //不是楼栋
_space.util.shopData = res.data;
}else{
res.data.forEach((item)=>{
for(let shop of item){
_space.util.shopData.push(...shop.shopList);
}
})
}
}
_space.initOptions(options);
});
}else{
console.log(e);
_space.backObj.code = 404;
_space.backObj.msg = "地图数据JSON格式错误";
_space.callBackLoadOver(_space.backObj);
_space.callBackLoadOver = null;
return;
}
});
},
initOptions: function (options) {
//初始化参数
if (this.util.allMap[this.util.selectBuild].playSpeed) {
this.util.allMap[this.util.selectBuild].hasOwnProperty('scale') && (this.util.options.mapScale = parseInt(this.util.allMap[this.util.selectBuild].scale))
this.util.allMap[this.util.selectBuild].hasOwnProperty('playSpeed') && (this.util.options.playSpeed = parseInt(this.util.allMap[this.util.selectBuild].playSpeed))
this.util.allMap[this.util.selectBuild].hasOwnProperty('collision') && (this.util.options.collision = this.util.allMap[this.util.selectBuild].collision)
this.util.allMap[this.util.selectBuild].hasOwnProperty('navColor') && (this.util.options.navColor = this.util.allMap[this.util.selectBuild].navColor)
this.util.allMap[this.util.selectBuild].hasOwnProperty('aRadius') && (this.util.options.aRadius = parseInt(this.util.allMap[this.util.selectBuild].aRadius))
this.util.allMap[this.util.selectBuild].hasOwnProperty('boxShop') && (this.util.options.boxShop = this.util.allMap[this.util.selectBuild].boxShop.split(','))
this.util.allMap[this.util.selectBuild].hasOwnProperty('shopStyle') && (this.util.options.shopStyle = this.util.allMap[this.util.selectBuild].shopStyle)
this.util.allMap[this.util.selectBuild].hasOwnProperty('modelIcon') && (this.util.options.modelIcon = this.util.allMap[this.util.selectBuild].modelIcon)
this.util.allMap[this.util.selectBuild].hasOwnProperty('facSize') && (this.util.options.facSize = this.util.allMap[this.util.selectBuild].facSize)
this.util.allMap[this.util.selectBuild].hasOwnProperty('m_scale') && (this.util.sceneGap.scale = this.util.allMap[this.util.selectBuild].m_scale)
this.hemiLight.color = new THREE.Color(this.util.allMap[this.util.selectBuild].s_col || '#fffff0')
this.hemiLight.groundColor = new THREE.Color(this.util.allMap[this.util.selectBuild].g_col || '#ffffff')
this.hemiLight.intensity = this.util.allMap[this.util.selectBuild].a_int || 0.5
this.shawLight.color = new THREE.Color(this.util.allMap[this.util.selectBuild].d_col || '#ffffff')
this.shawLight.intensity = this.util.allMap[this.util.selectBuild].d_int || 0.1
if (this.util.allMap[this.util.selectBuild].c_site && this.util.allMap[this.util.selectBuild].c_site.split(',')) {
this.util.sceneGap.cameraX = parseInt(this.util.allMap[this.util.selectBuild].c_site.split(',')[0]) || this.util.sceneGap.cameraX
this.util.sceneGap.cameraY = parseInt(this.util.allMap[this.util.selectBuild].c_site.split(',')[1]) || this.util.sceneGap.cameraY
this.util.sceneGap.cameraZ = parseInt(this.util.allMap[this.util.selectBuild].c_site.split(',')[2]) || this.util.sceneGap.cameraZ
}
if (this.util.allMap[this.util.selectBuild].m_site && this.util.allMap[this.util.selectBuild].m_site.split(',')) {
this.util.sceneGap.x = parseInt(this.util.allMap[this.util.selectBuild].m_site.split(',')[0]) || this.util.sceneGap.x
this.util.sceneGap.y = parseInt(this.util.allMap[this.util.selectBuild].m_site.split(',')[1]) || this.util.sceneGap.y
this.util.sceneGap.z = parseInt(this.util.allMap[this.util.selectBuild].m_site.split(',')[2]) || this.util.sceneGap.z
}
if (this.util.allMap[this.util.selectBuild].m_zoom) {
this.util.m_zoom = this.util.allMap[this.util.selectBuild].m_zoom
}
}
let { playSpeed, collision, modelIcon, shopStyle, shadow, otherPath, navColor, iconUrl, iconName, camZoom, inArea, pathColor, pathStyle } = options;
this.util.options.playSpeed = playSpeed != undefined ? playSpeed : this.util.options.playSpeed
this.util.options.collision = collision != undefined ? collision : this.util.options.collision
this.util.options.modelIcon = modelIcon != undefined ? modelIcon : this.util.options.modelIcon
this.util.options.shadow = shadow!= undefined ? shadow : this.util.options.shadow
this.util.options.shopStyle = shopStyle != undefined ? shopStyle : this.util.options.shopStyle
this.util.options.otherPath = otherPath != undefined ? otherPath : this.util.options.otherPath
this.util.options.navColor = navColor != undefined ? navColor : this.util.options.navColor
this.util.options.iconName = iconName != undefined ? iconName : this.util.options.iconName
this.util.options.camZoom = camZoom != undefined ? camZoom : this.util.options.camZoom
this.util.options.inArea = inArea!= undefined ? inArea : this.util.options.inArea
this.util.options.pathColor = pathColor != undefined ? pathColor : this.util.options.pathColor
this.util.options.pathStyle = pathStyle != undefined ? pathStyle : this.util.options.pathStyle
this.util.iconUrl = iconUrl != undefined ? iconUrl : []
if (!isNaN(Number(options.floor))) {
this.util.startObj.floor = this.util.deviceObj.floor = parseInt(options.floor) || 0
} else {
if (Array.isArray(this.util.allMap)) {
for (var iii = 0; iii < this.util.allMap[this.util.startObj.build].buildArr.length; iii++) {
if (this.util.allMap[this.util.startObj.build].buildArr[iii].name == options.floor) {
this.util.startObj.floor = this.util.deviceObj.floor = this.util.allMap[this.util.startObj.build].buildArr[iii].order
break
}
}
}
}
for(let k=0; k<this.util.allMap.length; k++){
for (let kk = 0; kk < this.util.allMap[k].buildArr.length; kk++) {
let floor = this.util.allMap[k].buildArr[kk].mapData;
if(floor.models){
for (let t = 0; t < floor.models.length; t++) {
for (let i = 0; i < this.util.modelStr.length; i++) {
if (floor.models[t].type == this.util.modelStr[i].key) {
this.util.modelStr[i].load = true;
break;
}
}
}
}
}
}
try {
this.initOutModel()
} catch (e) {
this.callBackLoadOver({ code: 404, msg: '地图数据解析失败' })
this.callBackLoadOver = null
}
},
//加载全局模型
initOutModel: function () {
let _this = this
if (this.util.initModelArr && this.util.initModelArr.length > 0) {
for (let i = 0; i < _this.util.initModelArr.length; i++) {
let loader = new THREE.GLTFLoader()
loader.load(_this.util.beforPath + _this.util.initModelArr[i].url, function (collada) {
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = _this.util.initModelArr[i].scale
collada.scene.position.set(_this.util.initModelArr[i].site.x, _this.util.initModelArr[i].site.y, _this.util.initModelArr[i].site.z)
collada.scene.rotation.set(
(_this.util.initModelArr[i].rot.x * Math.PI) / 180,
(_this.util.initModelArr[i].rot.y * Math.PI) / 180,
(_this.util.initModelArr[i].rot.z * Math.PI) / 180
)
collada.scene.userData.type = _this.util.initModelArr[i].type
for (let k = 0; k < collada.animations.length; k++) {
let mixer = new THREE.AnimationMixer(collada.scene)
mixer.clipAction(collada.animations[k]).play()
_this.mixers.push(mixer)
}
//////////////////////////////////////////////
collada.scene.traverse(function (child) {
if (child.type === 'Mesh') {
child.castShadow = false
child.receiveShadow = false
child.userData.opacity = child.material.opacity
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding //贴图需要转换成 线性编码
}
}
})
collada.scene.name = 'model' //删除其它元素时过滤
if (_this.util.initModelArr[i].type == 'out') {
_this.outModelGap.add(collada.scene)
} else if (_this.util.initModelArr[i].type == 'periphery') {
_this.peripheryGap.add(collada.scene)
}
})
if (i == _this.util.initModelArr.length - 1) {
for (let u = 0; u < _this.util.tipArr.length; u++) {
let prite = document.createElement('div')
prite.style.zIndex = 20
prite.innerHTML = _this.util.tipArr[u].htmlUrl
if (!_this.util.tipArr[u].click) {
prite.style.pointerEvents = 'none'
}
let pointLabel2 = new THREE.CSS2DObject(prite)
pointLabel2.position.set(_this.util.tipArr[u].x, _this.util.tipArr[u].z, _this.util.tipArr[u].y)
pointLabel2.userData.type = '2d_IP'
if (_this.util.tipArr[u].type == 'out') {
_this.outModelGap.add(pointLabel2)
} else if (_this.util.tipArr[u].type == 'periphery') {
_this.peripheryGap.add(pointLabel2)
}
}
_this.initBuild()
}
}
} else {
_this.util.changeDist.inner = _this.util.options.maxDis
_this.initBuild()
}
},
initBuild: function (e) {
this.util.pathStateObj.elevator = null;
this.util.pathStateObj.straight = null;
this.util.pathStateObj.elevatorDown = null;
let loader2 = new THREE.GLTFLoader()
let _this = this;
loader2.load(this.util.beforPath + 'static/img/zhong.glb', function (collada2) {
collada2.scene.scale.x = collada2.scene.scale.y = collada2.scene.scale.z = 100
collada2.scene.applyMatrix4(_this.sceneGap.matrix)
collada2.scene.renderOrder = 200
collada2.scene.traverse(function (child) {
if (child.type === "Mesh") {
child.castShadow = _this.util.options.shadow;
child.receiveShadow = _this.util.options.shadow;
child.userData.opacity = child.material.opacity;
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding; //贴图需要转换成 线性编码
}
}
});
collada2.scene.name = "Z-model";
for (let k = 0; k < collada2.animations.length; k++) {
let mixer = new THREE.AnimationMixer(collada2.scene)
mixer.clipAction(collada2.animations[k]).play()
Map_QM.mixers.push(mixer)
}
_this.endModel = collada2.scene
_this.scene.add(collada2.scene)
_this.endModel.visible = false
})
let spriteMap = new THREE.TextureLoader().load(_this.util.beforPath + 'static/img/Z.png')
let spriteMaterial = new THREE.SpriteMaterial({
//sizeAttenuation: false 禁止跟随鼠标缩放
map: spriteMap,
depthTest: true,
transparent: true,
alphaTest: 0.5
})
_this.endIcon = new MySprite_QM(spriteMaterial)
_this.endIcon.scale.set(100, 120, 1)
_this.endIcon.center = new THREE.Vector2(0.5, 0)
_this.endIcon.position.set(0, 55, 0)
_this.endIcon.applyMatrix4(_this.sceneGap.matrix)
_this.endIcon.renderOrder = 300
_this.endIcon.visible = false
_this.endIcon.name = "Z-model";
_this.scene.add(_this.endIcon)
if (_this.util.options.modelIcon) {
let loader = new THREE.GLTFLoader();
loader.load(_this.util.beforPath + "static/img/elevator.gltf", function (collada) {
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = _this.util.options.facSize || 20;
collada.scene.rotation.x = -90 * Math.PI / -180;
collada.scene.renderOrder = 300;
_this.util.pathStateObj.elevator = collada.scene;
new THREE.GLTFLoader().load(_this.util.beforPath + "static/img/elevatorDown.gltf", function (collada) {
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = _this.util.options.facSize || 20;
collada.scene.rotation.x = -90 * Math.PI / -180;
collada.scene.renderOrder = 300;
_this.util.pathStateObj.elevatorDown = collada.scene;
new THREE.GLTFLoader().load(_this.util.beforPath + "static/img/dt.gltf", function (collada) {
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = _this.util.options.facSize || 20;
collada.scene.rotation.x = -90 * Math.PI / -180;
collada.scene.renderOrder = 300;
_this.util.pathStateObj.straight = collada.scene;
_this.index = 0;
_this.initTreeModel();
});
});
});
} else {
_this.index = 0;
_this.initTreeModel();
}
},
loaderOver: function (e) {
this.sceneGap = new THREE.Group();
this.sceneGap.scale.set(this.util.sceneGap.scale, this.util.sceneGap.scale, this.util.sceneGap.scale);
this.scene.add(this.sceneGap);
this.buildObj = new THREE.Group();
this.sceneGap.add(this.buildObj);
this.CSSObject = new THREE.Object3D();
if(this.moveFloorbg){
this.moveFloorbg.userData.type = "moveFloor";
this.CSSObject.add(this.moveFloorbg);
}
this.CSSObject.add(this.outObject);
this.CSSObject.add(this.perObject);
this.buildObj.add(this.CSSObject);
this.buildObj.add(this.dtLineGroup);
this.initGuide();
if(!this.util.options.deviceAng){
this.cameraPerspective.position.set(this.util.sceneGap.cameraX, this.util.sceneGap.cameraY, this.util.sceneGap.cameraZ);
this.cameraPerspective.updateProjectionMatrix(); //必须update
this.cameraOrtho.position.set(this.util.sceneGap.cameraX, this.util.sceneGap.cameraY, this.util.sceneGap.cameraZ);
this.cameraOrtho.updateProjectionMatrix();
this.controls.target.set(this.util.sceneGap.x, this.util.sceneGap.y, this.util.sceneGap.z);
}
let pathData = this.util.allMap[parseInt(this.util.deviceObj.build)].buildArr[parseInt(this.util.deviceObj.floor)].mapData.path;
pathData && pathData.nodes.sort(this.util.sortNode);
if (parseInt(this.util.deviceObj.node) != -1) {
if (pathData && pathData.nodes.length > parseInt(this.util.deviceObj.node)) {
this.util.deviceObj.xaxis = pathData.nodes[parseInt(this.util.deviceObj.node)].x;
this.util.deviceObj.yaxis = pathData.nodes[parseInt(this.util.deviceObj.node)].y;
}
}
this.util.pathStateObj.facAllArr = [];
this.mapArr.length = 0;
this.util.pathStateObj.basePath = "{";
for (let bd = 0; bd < this.util.allMap.length; bd++) {
for (let i = 0; i < this.util.allMap[bd].buildArr.length; i++) {
this.convertPath(bd, i);
}
}
if (this.util.pathStateObj.basePath.length > 1) {
this.util.pathStateObj.basePath = this.util.pathStateObj.basePath.substr(0, this.util.pathStateObj.basePath.length - 1);
}
this.util.pathStateObj.basePath += "}";
let bjP = JSON.parse(this.util.pathStateObj.basePath);
if (this.util.options.otherPath) { //如果多楼栋需要配置楼栋之间通行路径
for (let item of this.util.options.otherPath) {
bjP[item.f][item.s] = item.d;
bjP[item.s][item.f] = item.d;
}
}
//初始化基础路径;
let jcStr = JSON.stringify(bjP);
let graphPathObj = JSON.parse(jcStr);
let ftPathObj = JSON.parse(jcStr);
let dtPathObj = JSON.parse(jcStr);
try {
for (let j = 0; j < this.util.pathStateObj.facAllArr.length; j++) {
for (let k = 0; k < this.util.pathStateObj.facAllArr[j].length; k++) {
let facP = this.util.pathStateObj.facAllArr[j][k].buildOrder + "_" + this.util.pathStateObj.facAllArr[j][k].floorOrder + "_" + this.util.pathStateObj.facAllArr[j][k].navCode;
for (let h = 0; h < this.util.pathStateObj.facAllArr[j].length; h++) {
if (h != k && this.util.pathStateObj.facAllArr[j][k].buildOrder == this.util.pathStateObj.facAllArr[j][h].buildOrder) {
let nP = this.util.pathStateObj.facAllArr[j][h].buildOrder + "_" + this.util.pathStateObj.facAllArr[j][h].floorOrder + "_" + this.util.pathStateObj.facAllArr[j][h].navCode;
if (this.util.pathStateObj.facAllArr[j][h].facCode == "dt") {
ftPathObj[facP][nP] = 6000 + 3000 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));;
if (this.util.pathStateObj.seldtFacNo.type == "dt" && this.util.pathStateObj.facAllArr[j][k].no == this.util.pathStateObj.seldtFacNo.no) {
graphPathObj[facP][nP] = 1000 + 400 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
} else {
graphPathObj[facP][nP] = 4000 + 800 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
}
dtPathObj[facP][nP] = 4000 + 800 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
} else if (this.util.pathStateObj.facAllArr[j][h].facCode == "td") {
graphPathObj[facP][nP] = 4000 + 800 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
ftPathObj[facP][nP] = 4000 + 800 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
dtPathObj[facP][nP] = 4000 + 800 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
} else {
dtPathObj[facP][nP] = 6000 + 3000 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
if (this.util.pathStateObj.seldtFacNo.type == "ft" && this.util.pathStateObj.seldtFacNo.no.search(this.util.pathStateObj.facAllArr[j][k].no+",") != -1) {
graphPathObj[facP][nP] = 1000 + 400 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
} else {
graphPathObj[facP][nP] = 4000 + 800 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
}
ftPathObj[facP][nP] = 4000 + 800 * Math.abs(parseInt(this.util.pathStateObj.facAllArr[j][h].floorOrder) - parseInt(this.util.pathStateObj.facAllArr[j][k].floorOrder));
}
}
}
}
}
} catch (e) {
console.log("交通设施点位问题: " + e);
}
this.util.pathStateObj.graphPath = graphPathObj;
this.util.pathStateObj.ftPath = ftPathObj;
this.util.pathStateObj.dtPath = dtPathObj;
var fIndex = 0, bIndex = 0;
this.mapArr[bIndex] = [];
intTimer = setInterval(() => {
if (!Map_QM.util.allMap[bIndex].buildArr[fIndex]) {
clearInterval(intTimer);
this.initFloor();
return;
}
let floor = new FloorMap_QM(bIndex, fIndex, Map_QM.util.allMap[bIndex].buildArr[fIndex].name);
floor.floorName = Map_QM.util.allMap[bIndex].buildArr[fIndex].name;
floor.initDraw();
floor.allObj.position.set(bIndex * Map_QM.util.options.bSpace, 0, 0);
if (fIndex != parseInt(Map_QM.util.deviceObj.floor)) {
floor.allObj.visible = false;
}
this.buildObj.add(floor.allObj);
this.mapArr[bIndex].push(floor);
fIndex++;
if (fIndex >= Map_QM.util.allMap[bIndex].buildArr.length) {
if (bIndex == Map_QM.util.allMap.length - 1) {
clearInterval(intTimer);
let pathData = Map_QM.util.allMap[parseInt(Map_QM.util.deviceObj.build)].buildArr[parseInt(Map_QM.util.deviceObj.floor)].mapData.path;
if (Map_QM.util.deviceObj.xaxis) {
Map_QM.mapArr[parseInt(Map_QM.util.deviceObj.build)][parseInt(Map_QM.util.deviceObj.floor)].setStartSite(Map_QM.util.deviceObj.xaxis, Map_QM.util.deviceObj.yaxis, parseInt(Map_QM.util.shopHeight)+20);
} else {
if (parseInt(Map_QM.util.deviceObj.node) != -1) {
pathData && pathData.nodes.sort(Map_QM.util.sortNode);
if (pathData && !Map_QM.util.deviceObj.xaxis && pathData.nodes.length > parseInt(Map_QM.util.deviceObj.node) && parseInt(Map_QM.util.deviceObj.node)>=0) {
Map_QM.util.deviceObj.xaxis = pathData.nodes[parseInt(Map_QM.util.deviceObj.node)].x;
Map_QM.util.deviceObj.yaxis = pathData.nodes[parseInt(Map_QM.util.deviceObj.node)].y;
} else {
console.warn("初始化点位失败");
}
Map_QM.mapArr[parseInt(Map_QM.util.deviceObj.build)][parseInt(Map_QM.util.deviceObj.floor)].setStartSite(Map_QM.util.deviceObj.xaxis, Map_QM.util.deviceObj.yaxis, parseInt(Map_QM.util.shopHeight)+20);
}
}
this.initFloor();
} else {
bIndex++;
fIndex = 0;
this.mapArr[bIndex] = [];
}
}
}, 0);
},
beforeDestroy:function() {
if (this.scene) {
this.renderer.dispose()
this.util.pathStateObj.basePath = null;
this.ele.removeEventListener("wheel", this.mouseWheel);
this.ele.removeEventListener("touchmove", this.mouseMove);
this.ele.removeEventListener('click', this.onMouseClickBox); //地图点击
this.ele.removeEventListener('touchend',this.mouseUp);
this.controls.removeEventListener('change', this.controlsChock);
document.removeEventListener('resize', this.changeDocmentResize); //窗口变化
this.remove_child(this.sceneGap);
this.scene.remove(this.sceneGap);
while ((elem = this.ele.firstChild)) {
elem.remove();
}
this.renderer.domElement = null
this.renderer = null
this.scene.clear()
this.scene = null
this.camera = null
this.controls = null
this.util.spriteMaterialArr = [];
this.util.lineBasicMaterialArr = [];
this.util.meshMaterialArr = [];
this.util.parkMaterialArr = [];
this.util.shopData = []; //店铺数据
this.util.iconUrl = [];
this.util.allMap = [];
this.util = null;
Map_QM = null;
}
},
initTreeModel: function () {
if(this.index < this.util.modelStr.length - 1 ){
if(this.util.modelStr[this.index].load){
this.gltfLoad(this.util.beforPath + this.util.modelStr[this.index].url);
}else{
this.index++;
this.initTreeModel();
}
}else{
if (this.util.allMap && this.util.allMap.length > 0) {
this.loaderOver();
}
}
},
gltfLoad: function (url) {
let sopce = this;
new THREE.GLTFLoader().load(url, function (object) {//加载路径fbx文件
object.scene.traverse(function (child) {
if (child.type === "Mesh") {
child.castShadow = sopce.util.options.shadow;
child.receiveShadow = sopce.util.options.shadow;
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding; //贴图需要转换成 线性编码
}
if (sopce.util.modelStr[sopce.index].colorModel === 'gama') {
child.material.color.convertGammaToLinear(0.6);
}
}
});
object.scene.children[0].scale.set(sopce.util.modelStr[sopce.index].size.x, sopce.util.modelStr[sopce.index].size.y, sopce.util.modelStr[sopce.index].size.z);
sopce.util.fbxModels.push({ 'key': sopce.util.modelStr[sopce.index].key, 'obj': object, 'operation': sopce.util.modelStr[sopce.index] });
if (sopce.index < sopce.util.modelStr.length - 1) {
sopce.index++;
sopce.initTreeModel();
} else {
if (sopce.util.allMap && sopce.util.allMap.length > 0) {
sopce.loaderOver();
}
}
});
},
initGuide: function () {
let _this = this
new THREE.GLTFLoader().load(_this.util.beforPath + 'static/img/runman.gltf', function (obj) {
obj.scene.scale.x = obj.scene.scale.y = obj.scene.scale.z = _this.util.options.facSize || 20
obj.scene.children[0].children[1].children[0].material.color = new THREE.Color(0xfe9219)
_this.sceneGap.add(obj.scene)
obj.scene.visible = false
obj.scene.children[0].rotation.x = Math.PI / 2
obj.scene.children[0].rotation.y = Math.PI
// obj作为参数创建一个混合器,解析播放obj及其子对象包含的动画数据
let mixer = new THREE.AnimationMixer(obj.scene)
let AnimationAction = mixer.clipAction(obj.animations[0])
AnimationAction.timeScale = 2
AnimationAction.play()
_this.mixers.push(mixer)
_this.man_3d = obj.scene
_this.guide = _this.man_3d
})
new THREE.GLTFLoader().load(this.util.beforPath + "static/img/guide.glb", function (obj) {
obj.scene.scale.x = obj.scene.scale.y = obj.scene.scale.z = _this.util.options.facSize*5 || 100;
obj.scene.visible = false;
obj.scene.children[0].rotation.x = Math.PI / 2;
obj.scene.traverse(function (child) {
if (child.type === "Mesh") {
child.castShadow = _this.util.options.shadow;
child.receiveShadow = _this.util.options.shadow;
child.userData.opacity = child.material.opacity;
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding; //贴图需要转换成 线性编码
}
}
});
for (let k = 0; k < obj.animations.length; k++) {
let mixer = new THREE.AnimationMixer(obj.scene)
mixer.clipAction(obj.animations[k]).play()
_this.mixers.push(mixer)
}
_this.man_2d = obj.scene;
_this.man_2d.renderOrder = 160;
_this.sceneGap.add(_this.man_2d);
});
},
initFloor: function () {
this.controls.saveState();
this.changeBuild(this.util.deviceObj.build, this.util.deviceObj.floor);
//初始化方向为第一人称方向
this.util.options.deviceAng && this.rotationAngle(this.util.deviceObj.angle)
this.startRender();
setTimeout(() => {
Map_QM.controls.addEventListener('change', Map_QM.controlsChock); //控制器变化
let boundBox = new THREE.Box3();
boundBox.setFromObject(Map_QM.sceneGap);
if (isNaN(boundBox.min.x) || isNaN(boundBox.min.y) ){
Map_QM.controls.minPan = new THREE.Vector3(Map_QM.w / -8, 0, Map_QM.h / -8);
Map_QM.controls.maxPan = new THREE.Vector3(Map_QM.w / 8, 0, Map_QM.h / 8);
} else{
boundBox.min.x<-400 && (boundBox.min.x=boundBox.min.z)
boundBox.max.x>400 && (boundBox.max.x=boundBox.max.z)
boundBox.min.z<-400 && (boundBox.min.z=boundBox.min.x)
boundBox.max.z>400 && (boundBox.max.z=boundBox.max.x)
Map_QM.controls.minPan = boundBox.min;
Map_QM.controls.maxPan = boundBox.max;
}
}, 150)
},
calcFov:function (d, w, r) {
let f;
let vertical = w;
if (r < 1) {
vertical = vertical/r;
}
f = Math.atan(vertical/d/2)* 2 * (180 / Math.PI);
return f;
},
/**
* 解析路径
*/
convertPath: function (buildOrder, floorOrder) {
let mapDataA = this.util.allMap[buildOrder].buildArr[floorOrder].mapData;
let pathData = mapDataA.path;
if (!pathData) {
return;
}
if (pathData.nodes.length > 0) {
pathData.nodes.sort(this.util.sortNode);
for (let i = 0; i < pathData.nodes.length; i++) {
let a = pathData.nodes[i].id;
this.util.pathStateObj.basePath += "\"" + buildOrder + "_" + floorOrder + "_" + a + "\":{";
for (let n = 0; n < pathData.nodes[i]["list"].length; n++) {
let b;
if (pathData.nodes[i]["list"][n].id || pathData.nodes[i]["list"][n].id == "0") {
b = pathData.nodes[i]["list"][n].id;
} else {
b = a == pathData.nodes[i]["list"][n].selfNode.id ? pathData.nodes[i]["list"][n].nextNode.id : pathData.nodes[i]["list"][n].selfNode.id;
}
this.util.pathStateObj.basePath += "\"" + buildOrder + "_" + floorOrder + "_" + b + "\":" + pathData.nodes[i]["list"][n].cost + ",";
}
if (pathData.nodes[i]["list"].length > 0) {
this.util.pathStateObj.basePath = this.util.pathStateObj.basePath.substr(0, this.util.pathStateObj.basePath.length - 1);
}
this.util.pathStateObj.basePath += "},";
}
}
let mindt = 10000,
minupft = -1,
mindownft = -1,
seldtNo,seldownftNo,selupftNo;
if (buildOrder == this.util.deviceObj.build && floorOrder == this.util.deviceObj.floor && parseInt(this.util.deviceObj.node)>=0) {
if (pathData && !this.util.deviceObj.xaxis && pathData.nodes.length > parseInt(this.util.deviceObj.node) && parseInt(this.util.deviceObj.node)>0) {
this.util.deviceObj.xaxis = pathData.nodes[parseInt(this.util.deviceObj.node)].x
this.util.deviceObj.yaxis = pathData.nodes[parseInt(this.util.deviceObj.node)].y
}
//获取本楼层最近的电梯
for (let n = 0; n < mapDataA.stairs.length; n++) {
if (mapDataA.stairs[n].state && mapDataA.stairs[n].no != '' && parseInt(mapDataA.stairs[n].navCode) > 0) {
let ms = Math.abs(parseInt(mapDataA.stairs[n].x) - parseInt(this.util.deviceObj.xaxis)) + Math.abs(parseInt(mapDataA.stairs[n].y) - parseInt(this.util.deviceObj.yaxis))
if (mindt > ms && (mapDataA.stairs[n].facCode == "ft" || mapDataA.stairs[n].facCode=="upft" || mapDataA.stairs[n].facCode=="downft" || mapDataA.stairs[n].facCode=="dt")) {
mindt = ms
let fac = mapDataA.stairs[n].facCode == "dt" ? "dt":"ft";
this.util.pathStateObj.seldtFacNo.type = fac;
if (mapDataA.stairs[n].facCode == 'dt') {
seldtNo = mapDataA.stairs[n].no
}
}
}
}
if(this.util.pathStateObj.seldtFacNo.type == "dt"){
this.util.pathStateObj.seldtFacNo.no = seldtNo;
}else{
for(let t=0; t<this.util.allMap[buildOrder].buildArr.length; t++){
let mapData = this.util.allMap[buildOrder].buildArr[t].mapData
minupft = 100000;
mindownft = 100000;
selupftNo = "";
seldownftNo = "";
for (let h = 0; h < mapData.stairs.length; h++) {
if (mapData.stairs[h].state && mapData.stairs[h].no != '' && parseInt(mapData.stairs[h].navCode) > 0) {
let ms = Math.abs(parseInt(mapData.stairs[h].x) - parseInt(this.util.deviceObj.xaxis)) + Math.abs(parseInt(mapData.stairs[h].y) - parseInt(this.util.deviceObj.yaxis))
if (mapData.stairs[h].facCode == 'upft' || mapData.stairs[h].downState) {
//上扶
if (minupft > ms) {
minupft = ms
selupftNo = mapData.stairs[h].no
}
} else if (mapData.stairs[h].facCode == 'downft' || mapData.stairs[h].upState) {
if (mindownft > ms) {
mindownft = ms
seldownftNo = mapData.stairs[h].no;
}
}
}
}
//扶梯距离最小
selupftNo != "" && (this.util.pathStateObj.seldtFacNo.no += (selupftNo+","));
seldownftNo != "" && (this.util.pathStateObj.seldtFacNo.no += (seldownftNo+","));
}
}
//console.log(this.util.pathStateObj.seldtFacNo);
}
let noHas;
for (let j = 0; j < mapDataA.stairs.length; j++) {
if (parseInt(mapDataA.stairs[j].navCode) > 0 && mapDataA.stairs[j].state) { //排除禁用的设施
noHas = true;
for (let k = 0; k < this.util.pathStateObj.facAllArr.length; k++) { //Map_QM.util.pathStateObj.facAllArr 记录遍历结果
if (this.util.pathStateObj.facAllArr[k][0].no != "" && this.util.pathStateObj.facAllArr[k][0].navCode != "" && parseInt(this.util.pathStateObj.facAllArr[k][0].navCode) >0 && this.util.pathStateObj.facAllArr[k][0].no == mapDataA.stairs[j].no) {
if (this.util.pathStateObj.facAllArr[k][0].facCode == mapDataA.stairs[j].facCode || (this.util.pathStateObj.facAllArr[k][0].facCode.search("ft") != -1 && mapDataA.stairs[j].facCode.search("ft") != -1)) {
noHas = false;
mapDataA.stairs[j].floorOrder = floorOrder;
mapDataA.stairs[j].buildOrder = buildOrder;
this.util.pathStateObj.facAllArr[k].push(mapDataA.stairs[j]);
}
}
}
if (noHas) {
mapDataA.stairs[j].buildOrder = buildOrder;
mapDataA.stairs[j].floorOrder = floorOrder;
let array = [mapDataA.stairs[j]];
this.util.pathStateObj.facAllArr.push(array);
}
}
}
},
/**
* @api {方法} changeMapState("3d") 地图状态切换
* @apiGroup 地图显示
* @apiDescription 地图展示状态切换
* @apiVersion 2.0.0
* @apiParam {string} state 地图状态
*
* @apiSampleRequest off
*
* @apiParamExample {String} 请求示例
*
* Map_QM.changeMapState("2d");
*
*/
changeMapState: function (state) {
Map_QM.controls.reset()
Map_QM.util.options.deviceAng && Map_QM.rotationAngle(Map_QM.util.deviceObj.angle)
if (state === '3d') {
Map_QM.camera = Map_QM.cameraPerspective;
Map_QM.controls.object = Map_QM.camera;
Map_QM.shawLight.castShadow = Map_QM.util.options.shadow;
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.2;
Map_QM.controls.setZoom(1);
Map_QM.changeIconState(state);
} else {
Map_QM.camera = Map_QM.cameraOrtho;
Map_QM.controls.object = Map_QM.camera;
Map_QM.shawLight.castShadow = false;
Map_QM.controls.setZoom(Map_QM.util.m_zoom);
Map_QM.controls.maxPolarAngle = 0;
Map_QM.changeIconState(state);
}
},
changeIconState: function (state,fIndex=-1) {
iconState = state;
fIndex = fIndex === -1 ? Map_QM.util.selectFloor : fIndex;
for (let i = 0; i < Map_QM.mapArr[Map_QM.util.selectBuild].length; i++) {
if(i == fIndex){
Map_QM.mapArr[Map_QM.util.selectBuild][i].serObj.traverse((obj) => {
if (obj.userData && obj.userData.use) {
if (obj.userData.use != "all" && obj.userData.use != state) {
obj.visible = false;
obj.element && (obj.element.style.display = "none");
} else {
obj.visible = true;
obj.element && (obj.element.style.display = "");
}
}
});
}
}
if (Map_QM.devModel) {
Map_QM.devModel.visible = !Map_QM.util.pathStateObj.isPathState ? true : false;
}
if (Map_QM.qiModel) {
Map_QM.qiModel.visible = (state == "3d" && Map_QM.util.pathStateObj.isPathState) ? true : false;
}
if (Map_QM.qiIcon) {
Map_QM.qiIcon.visible = (state == "2d" && Map_QM.util.pathStateObj.isPathState) ? true : false;
}
},
/**
* @api {方法} changeBuild(buildOrder,floorOrder) 楼栋切换
* @apiGroup 地图交互
* @apiDescription 楼栋切换 传入楼栋编号,楼层编号
* @apiVersion 2.0.0
* @apiParam {int} buildOrder 传入楼栋编号(默认 0)
* @apiParam {int} floorOrder 传入楼栋编号(默认 0)
*
* @apiSampleRequest off
*
* @apiParamExample {int, int} 请求示例
*
* Map_QM.changeBuild(0, 0);
*
*/
changeBuild: function (buildOrder = 0, floorOrder = 0) {
Map_QM.changeMapModel("3D");
Map_QM.resetFloorState()
Map_QM.controls.reset();
Map_QM.util.options.deviceAng && Map_QM.rotationAngle(Map_QM.util.deviceObj.angle)
Map_QM.clearFloor(Map_QM.util.selectFloor)
this.changeBuildInner(buildOrder, floorOrder)
},
changeBuildInner: function (build = -1, fIndex = -1) {
fIndex = fIndex == -1 ? parseInt(Map_QM.util.deviceObj.floor) : fIndex
build = build == -1 ? parseInt(Map_QM.util.deviceObj.build) : build
Map_QM.util.selectBuild = build
TweenMax.to(Map_QM.buildObj.position, 0.5, {
x: build * Map_QM.util.options.bSpace * -1,
onComplete: function () {
Map_QM.changeFloorInner(build, fIndex) //结束后切换楼层
renderCount=0
}
})
},
resetFloorState: function () {
TweenMax.killAll(true);
Map_QM.util.pathStateObj.isPathState = false
Map_QM.controls.maxDistance = Map_QM.util.options.maxDis
clearTimeout(Map_QM.util.timeObj.collTime)
Map_QM.controls.enabled = true
Map_QM.controls.enableRotate = true
Map_QM.controls.minAzimuthAngle = -Infinity
Map_QM.controls.maxAzimuthAngle = Infinity
Map_QM.util.pathStateObj.forShopArr = { direction: '', wayList: [] }
if (Map_QM.guide && Map_QM.guide.visible) {
Map_QM.guide.visible = false
}
if (Map_QM.endModel && Map_QM.endModel.visible) {
Map_QM.endModel.visible = false
}
},
/**
* @api {方法} showFloor(floorOrder) 通过楼层编号切换楼层
* @apiGroup 地图交互
* @apiDescription 楼层切换,传入楼层编号,编号从下到上排序,最下面是0
* @apiVersion 2.0.0
*
* @apiParam {int} floorOrder 楼层编号
*
* @apiSampleRequest off
*
* @apiParamExample {int} 请求示例
*
* Map_QM.showFloor(1);
*
*/
showFloor: function (fIndex = -1, callBack = undefined) {
Map_QM.changeStartPoint();
Map_QM.changeMapModel("3D");
Map_QM.resetFloorState();
Map_QM.controls.reset();
Map_QM.util.options.deviceAng && Map_QM.rotationAngle(Map_QM.util.deviceObj.angle)
Map_QM.clearFloor(fIndex);
if (fIndex != -1) {
Map_QM.changeFloorInner(-1, fIndex, callBack);
}
},
/**
* @api {方法} changeFloorByName(floorOrder) 通过楼层名称切换楼层
* @apiGroup 地图交互
* @apiDescription 楼层切换,传入楼层名称,
* @apiVersion 2.0.0
*
* @apiParam {String} floorName 楼层名称
*
* @apiSampleRequest off
* @apiParamExample {String} 请求示例
*
* Map_QM.changeFloorByName("L1");
*/
changeFloorByName: function (floorName) {
let floors = Map_QM.mapArr[Map_QM.util.selectBuild]
for (let i = 0; i < floors.length; i++) {
if (floors[i].floorName == floorName) {
Map_QM.showFloor(floors[i].floorOrder)
return
}
}
},
changeFloorInner: function (build = -1, fIndex = -1, callBack = undefined, endIndex = -1, midIndex = -1) {
fIndex = fIndex != -1 ? fIndex : Map_QM.util.deviceObj.floor;
build = build != -1 ? build : Map_QM.util.deviceObj.build;
for (let t = 0; t < Map_QM.mapArr.length; t++) {
for (let i = 0; i < Map_QM.mapArr[t].length; i++) {
Map_QM.mapArr[t][i].allObj.visible = t == build ? true : false;
Map_QM.mapArr[t][i].CSSObj.traverse((obj) => {
obj.element && (obj.element.style.display = "none");
});
}
}
if (Map_QM.mapArr[build] && Map_QM.mapArr[build][fIndex]) {
Map_QM.mapArr[build][fIndex].allObj.visible = true;
} else {
return;
}
for (let i = 0; i < Map_QM.mapArr[build].length; i++) {
if (i == fIndex) {
Map_QM.mapArr[build][i].allObj.visible = true;
Map_QM.mapArr[build][i].CSSObj.traverse((obj) => {
obj.element && obj.userData.isShow && obj.userData.type== "icon" && (obj.element.style.display = "");
});
Map_QM.changeIconState(iconState,fIndex);
} else {
Map_QM.mapArr[build][i].allObj.visible = false;
}
if (i == Map_QM.mapArr[build].length - 1) {
if (build == Map_QM.util.selectBuild && fIndex == Map_QM.util.selectFloor) {
if (callBack) callBack();
Map_QM.timeOutInit();
} else {
Map_QM.util.selectBuild = build;
Map_QM.util.selectFloor = fIndex;
if (Map_QM.util.options.shadow) {
TweenMax.fromTo(Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.position, 0.2, { z: Map_QM.util.options.fSpace }, {
z: 0, ease: Cubic.easeIn, onComplete: function () {
Map_QM.timeOutInit();
if (callBack) callBack();
}
});
} else {
Map_QM.timeOutInit()
if (callBack) callBack()
}
}
}
}
},
/**
* @api {方法} onShowMeDir() 我的方向
* @apiGroup 地图显示
* @apiDescription 我的方向
* @apiVersion 2.0.0
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.onShowMeDir();
*
*/
onShowMeDir: function () {
if (Map_QM.util.pathStateObj.isPathState) {
Map_QM.changePathDir("2D");
}else{
this.onInnerMeDir()
}
},
onInnerMeDir: function () {
if (this.util.selectBuild != this.util.deviceObj.build || this.util.selectFloor != this.util.deviceObj.floor) {
this.changeFloorInner(this.util.deviceObj.build, this.util.deviceObj.floor)
}
TweenMax.killAll(true)
this.changeMapModel("2D")
Map_QM.controls.reset()
clearTimeout(shopTime)
isJUZ=false;
Map_QM.controls.minPolarAngle = 0
if (Map_QM.util.deviceObj.xaxis || Map_QM.util.deviceObj.yaxis) {
Map_QM.mapToPoint(Map_QM.util.deviceObj.xaxis, Map_QM.util.deviceObj.yaxis, 0)
} else {
Map_QM.mapToPoint(0, 0, 0)
}
Map_QM.controls.setZoom(Map_QM.util.options.camZoom)
Map_QM.rotationAngle(Map_QM.util.deviceObj.angle)
Map_QM.controls.enableRotate = false
},
changeMapModel: function (model) {
if (model == '2D') {
Map_QM.util.setModelState('2d')
Map_QM.controls.maxPolarAngle = 0
Map_QM.camera = Map_QM.cameraOrtho
Map_QM.controls.object = Map_QM.camera
Map_QM.camera.updateProjectionMatrix()
} else {
Map_QM.util.setModelState('3d')
Map_QM.camera = Map_QM.cameraPerspective
Map_QM.controls.object = Map_QM.camera
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.02
Map_QM.camera.updateProjectionMatrix()
}
Map_QM.updateRender();
},
/**
* @api {方法} onShowLocalSite(0) 局部显示放大
* @apiGroup 地图显示
* @apiDescription 局部显示放大 point 传入放大目标点,zoom放大级别 1-5
* @apiVersion 2.0.0
* @apiParam {Object} point 放大的地图位置
*
* @apiSampleRequest off
*
* @apiParamExample {Object} 请求示例
*
* Map_QM.onShowLocalSite({x:0,y:0},1);
*
*/
onShowLocalSite: function (centerPoint, juZ=true) {
Map_QM.controls.setZoom(1)
Map_QM.controls.reset()
if (Map_QM.util.initModelArr.length > 0 && Map_QM.util.changeDist.inner > Map_QM.util.options.minDis) {
Map_QM.controls.maxDistance = Map_QM.util.changeDist.inner;
}
Map_QM.mapToPoint(centerPoint.x, centerPoint.y, 0);
isJUZ = juZ;
},
//底图二维坐标转 3D模型三维坐标
mapToPoint: function (mapX, mapY, mapZ) {
let tag0 = Map_QM.controls.target
let pos0 = Map_QM.controls.object.position
let vct = new THREE.Vector3(mapX, -1 * mapY, mapZ)
vct.applyMatrix4(Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.matrix);
vct.applyMatrix4(Map_QM.sceneGap.matrix)
Map_QM.controls.target = new THREE.Vector3(vct.x, vct.y, vct.z )
Map_QM.controls.object.position.set(pos0.x+(vct.x-tag0.x), pos0.y+(vct.y-tag0.y), pos0.z+(vct.z-tag0.z))
return vct;
},
/**
* @api {方法} onShowDeviceSite() 地图方向复位
* @apiGroup 地图显示
* @apiDescription 地图方向复位
* @apiVersion 2.0.0
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.onShowDeviceSite();
*
*/
onShowDeviceSite: function () {
this.showFloor(this.util.deviceObj.floor)
},
/**
* 在2D 状态下平移镜头
*/
moveCameraBy2D: function (obj) {
if (pathCameraState == "2D" && Map_QM.camera == Map_QM.cameraOrtho) {
Map_QM.controls.minAzimuthAngle = Map_QM.util.deviceObj.angle * Math.PI / -180;
Map_QM.controls.maxAzimuthAngle = Map_QM.util.deviceObj.angle * Math.PI / -180;
Map_QM.mapToPoint(obj.x, obj.y, 0);
Map_QM.controls.update();
}
},
/**
* 方向复位
*/
resetMeDir: function () {
this.util.setModelState("3d");
this.changeMapState("3d");
this.controls.setZoom(1);
this.controls.minAzimuthAngle = -Infinity;
this.controls.maxAzimuthAngle = Infinity;
this.shawLight.castShadow = this.util.options.shadow;
this.controls.reset();
setTimeout(()=>{
this.util.options.deviceAng && this.rotationAngle(this.util.deviceObj.angle)
},500)
},
/**
* @api {方法} changePathDir(pathState) 切换导航方向
* @apiGroup 地图交互
* @apiDescription 切换导航方向
* @apiVersion 2.0.0
*
* @apiParam {String} pathState 地图导航方向(默认 3D)
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.changePathDir("2D");
*
*/
changePathDir: function (pathState = '3D') {
if (Map_QM.util.pathStateObj.isPathState) { //导航状态
let initVis = false;
if (Map_QM.endModel && Map_QM.endIcon) {
initVis = pathCameraState == "2D" ? Map_QM.endIcon.visible : Map_QM.endModel.visible;
}
pathCameraState = pathState;
if (Map_QM.endModel && Map_QM.endIcon) {
Map_QM.endModel.visible = pathCameraState == "2D" ? false : initVis;
Map_QM.endIcon.visible = pathCameraState == "2D" ? initVis : false;
}
Map_QM.reSetGuide();
Map_QM.pathRePlay();
}
},
reSetGuide: function () {
if (pathCameraState == "2D") { //2D导航
Map_QM.onInnerMeDir();
Map_QM.guide.visible = false;
let pos = Map_QM.guide.position;
Map_QM.guide = Map_QM.man_2d;
Map_QM.guide.position.x = pos.x;
Map_QM.guide.position.y = pos.y;
Map_QM.guide.visible = true;
Map_QM.controls.enabled = false;
} else {
Map_QM.resetMeDir();
Map_QM.controls.enabled = true;
Map_QM.controls.enableRotate = true;
Map_QM.guide.visible = false;
let pos = Map_QM.guide.position;
Map_QM.guide = Map_QM.man_3d;
Map_QM.guide.position.x = pos.x;
Map_QM.guide.position.y = pos.y;
Map_QM.guide.visible = true;
}
},
/**
* @api {方法} queryObject3DByShopNum(ipName) 获取3D对象
* @apiGroup 地图交互
* @apiDescription 获取3D对象
* @apiVersion 2.0.0
* @apiParam {string} ipName POI名称
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.queryObject3DByShopNum("L1001");
*
*/
queryObject3DByShopNum: function (ipName) {
for (let b = 0; b < Map_QM.mapArr.length; b++) {
for (let i = 0; i < Map_QM.mapArr[b].length; i++) {
let shopArr = Map_QM.mapArr[b][i].shopObj.children
for (let k = 0; k < shopArr.length; k++) {
if (shopArr[k].name == ipName) {
return shopArr[k]
}
}
}
}
return null
},
/**
* @api {方法} parseSelectShop() 设置选中店铺弹跳
* @apiGroup 地图交互
* @apiDescription 设置选中店铺弹跳
* @apiVersion 2.0.0
*
* @apiParam {object3D} selObject 传入3D对象
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.parseSelectShop(object);
*
*/
parseSelectShop: function (selObject) {
if (selObject) {
Map_QM.selectShop = selObject
TweenMax.to(Map_QM.selectShop.scale, 0.5, {
z: 3, repeat: 4, yoyo: true, ease: Cubic.easeIn,
onComplete: function () {
if (Map_QM.selectShop) {
TweenMax.to(Map_QM.selectShop.scale, 0.5, { z: 1 });
}
}
});
if (Map_QM.util.options.inArea && Map_QM.camera != Map_QM.cameraOrtho) {
Map_QM.onShowLocalSite(new Map_QM.util.Point(Map_QM.selectShop.xaxis, Map_QM.selectShop.yaxis));
}
}
},
/**
* @api {方法} cancelSelectShop() 取消店铺弹跳
* @apiGroup 地图交互
* @apiDescription 取消店铺弹跳效果
* @apiVersion 2.0.0
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.cancelSelectShop();
*
*/
cancelSelectShop: function () {
TweenMax.killAll(true)
if (Map_QM.selectShop) {
Map_QM.selectShop.scale.z = 1
}
},
/**
* @api {方法} changeStateShopPro(isShow) 店铺促销标签
* @apiGroup 地图交互
* @apiDescription 店铺促销标签展示/隐藏
* @apiVersion 2.0.0
*
* @apiParam {boolean} isShow 店铺促销标签是否显示(默认 false)
*
* @apiSampleRequest off
*
* @apiParamExample {boolean} 请求示例
*
* Map_QM.changeStateShopPro(true);
*
*/
changeStateShopPro: function (isShow = false) {
if(Map_QM.mapArr[Map_QM.util.selectBuild]){
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].tagObj.traverse((obj) => {
obj.element && (obj.element.style.visibility = isShow?"visible":"hidden")
});
}
},
/**
* @api {方法} changeShowTagObjState(isShow) 自定义标签
* @apiGroup 地图交互
* @apiDescription 自定义标签展示/隐藏
* @apiVersion 2.0.0
*
* @apiParam {boolean} isShow 自定义标签是否显示(默认 false)
*
* @apiSampleRequest off
*
* @apiParamExample {boolean} 请求示例
*
* Map_QM.changeShowTagObjState(true);
*
*/
changeShowTagObjState: function (isShow = false) {
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].showTagObj.traverse(obj => {
obj.visible = isShow
})
},
/**
* @api {方法} queryShopList() 获取店铺列表信息
* @apiGroup 地图数据
* @apiDescription 店铺列表
* @apiVersion 2.0.0
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.queryShopList()
*
*/
queryShopList: function () {
return JSON.parse(JSON.stringify(Map_QM.util.shopData))
},
/**
* @api {方法} rotationAngle(angle) 改变水平角度
* @apiGroup 地图显示
* @apiDescription 改变地图水平角度 angle>-180 && angle<180
* @apiVersion 2.0.0
*
* @apiParam {int} angle 旋转角度
*
* @apiSampleRequest off
*
* @apiParamExample {int} 请求示例
*
* Map_QM.rotationAngle(90);
*
*/
rotationAngle: function (angle) {
Map_QM.controls.setRotateHorizontal(Map_QM.controls.getRotateHorizontal());
Map_QM.controls.setRotateHorizontal(angle / 180 * Math.PI)
},
/**
* @api {方法} rotateAngle(angle) 改变垂直角度
* @apiGroup 地图显示
* @apiDescription 改变地图垂直角度 angle>-90 && angle<90
* @apiVersion 2.0.0
*
* @apiParam {int} angle 旋转角度
*
* @apiSampleRequest off
*
* @apiParamExample {int} 请求示例
*
* Map_QM.rotateAngle(-45);
*
*/
rotateAngle: function (angle) {
Map_QM.controls.rotate(angle / 180 * Math.PI)
},
/**
* @api {方法} setCameraDist(cDist) 调整地图大小
* @apiGroup 地图显示
* @apiDescription 调整地图大小(值越小地图越大) Map_QM.util.options.minDis ~ Map_QM.util.options.maxDis
* @apiVersion 2.0.0
*
* @apiParam {int} cDist 摄像头距离
*
* @apiSampleRequest off
*
* @apiParamExample {int} 请求示例
*
* Map_QM.setCameraDist(150);
*
*/
setCameraDist: function (cDist) {
if (Map_QM.util.options.minDis < parseInt(cDist) && parseInt(cDist) < Map_QM.util.options.maxDis) {
let oldObj = { dis: Map_QM.controls.getDistance() }
TweenMax.killAll(true)
TweenMax.to(oldObj, 0.5, {
dis: cDist,
onUpdate: function () {
Map_QM.controls.setDistance(oldObj.dis)
Map_QM.controlsChock()
}
})
}
},
/**
* @api {方法} startRender() 启动地图渲染
* @apiGroup 地图显示
* @apiDescription 启动地图渲染 与 cancelRender 配合使用可节约资源
* @apiVersion 2.0.0
*
* @apiSampleRequest off
* @apiParamExample 请求示例
*
* Map_QM.startRender();
*
*/
startRender: function () {
Map_QM.cancelRender()
let T = Map_QM.util._clock.getDelta()
Map_QM.controls.update();
Map_QM.renderer.render(Map_QM.scene, Map_QM.camera);
Map_QM.labelRenderer.render(Map_QM.scene, Map_QM.camera);
if(renderCount<3){
if(Map_QM.mapArr[Map_QM.util.selectBuild] && Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor]){
Map_QM.labelRenderer.renderObject( Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].CSSObj, Map_QM.camera );
}
renderCount++;
}
Map_QM.CSSObject && Map_QM.labelRenderer.renderObject( Map_QM.CSSObject, Map_QM.camera);
for (let item of Map_QM.mixers) {
item.update(T)
}
if (debug) {
stats.update()
}
renderFrame = requestAnimationFrame(Map_QM.startRender)
},
/**
* @api {方法} cancelRender() 取消地图渲染
* @apiGroup 地图显示
* @apiDescription 取消地图渲染 与 startRender 配合使用可节约资源
* @apiVersion 2.0.0
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.cancelRender();
*
*/
cancelRender: function () {
window.cancelAnimationFrame(renderFrame)
renderFrame = -1
},
/**
* @api {方法} addElementLabel() 地图html标签
* @apiGroup 地图交互
* @apiDescription 地图显示Html标签,返回3d标签对象
* @apiVersion 2.0.0
*
* @apiParam {Element} divObj div对象
* @apiParam {int} x 显示X坐标
* @apiParam {int} y 显示Y坐标
* @apiParam {int} z 显示高度坐标(默认 50)
* @apiParam {String} type docment元素自定义标识(默认 "shopInfo")
* @apiSampleRequest off
*
* @apiParamExample {String} 请求示例
* Map_QM.addElementLabel(divObj,x,y);
*/
addElementLabel: function (divObj, x, y, z = 50, type = 'shopInfo') {
divObj.style.opacity = 0
Map_QM.elementDestroy(type)
let shopInfo = new THREE.CSS2DObject(divObj);
shopInfo.position.set(x, -1 * y, z);
shopInfo.applyMatrix4(Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.matrix);
shopInfo.userData.type = type
shopInfo.userData.isShow = false
shopInfo.userData.floor = parseInt(Map_QM.util.selectFloor)
Map_QM.CSSObject.add(shopInfo)
TweenMax.to(divObj.style, 0.2, { opacity: 1, delay: 0.1 })
return shopInfo
},
/**
* @api {方法} updateElementPosition() 修改标签位置
* @apiGroup 地图交互
* @apiDescription 修改标签位置
* @apiVersion 2.0.0
* @apiParam {Object} obj 对象
* @apiParam {int} x 新的X坐标
* @apiParam {int} y 新的Y坐标
*
* @apiSampleRequest off
*
* @apiParamExample {Object} 请求示例
*
* Map_QM.updateElementPosition(obj,x,y);
*
*/
updateElementPosition: function (obj, x, y) {
if (obj.hasOwnProperty('position')) {
let h = obj.position.z
obj.position.set(x, -1 * y, h)
obj.applyMatrix4(Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.matrix)
}
},
/**
* @api {方法} elementDestroy(type) 销毁地图标签
* @apiGroup 地图交互
* @apiDescription 销毁地图上的html标签
* @apiVersion 2.0.0
* @apiParam {String} type docment元素自定义标识(默认 "shopInfo")
*
* @apiSampleRequest off
*
* @apiParamExample {Object} 请求示例
*
* Map_QM.elementDestroy();
*
*/
elementDestroy: function (type = "shopInfo") {
if(!Map_QM.CSSObject){
return;
}
for (let i = Map_QM.CSSObject.children.length - 1; i >= 0; i--) {
if(Map_QM.CSSObject.children[i].userData.type != "moveFloor"){
if(type== "all"){
Map_QM.CSSObject.children[i].element.style.visibility = "hidden";
Map_QM.CSSObject.remove(Map_QM.CSSObject.children[i]);
}else{
if (Map_QM.CSSObject.children[i].userData && Map_QM.CSSObject.children[i].userData.type == type) {
Map_QM.CSSObject.children[i].element.style.visibility = "hidden";
Map_QM.CSSObject.remove(Map_QM.CSSObject.children[i]);
}
}
}
}
},
/**
* @param {Object} e
* 地图BOX点击
*/
onMouseClickBox: function (event) {
let mouse = new THREE.Vector2()
mouse.x = (event.offsetX / Map_QM.w) * 2 - 1
mouse.y = -(event.offsetY / Map_QM.h) * 2 + 1
Map_QM.onCallTouchORMouse(mouse)
},
onCallTouchORMouse: function (mouse) {
if (!Map_QM.mapArr[Map_QM.util.selectBuild] && !Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor]) {
return
}
let raycaster = new THREE.Raycaster()
raycaster.setFromCamera(mouse, Map_QM.camera)
let intersects = raycaster.intersectObjects(Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.children, true)
let clickShop = false
//图标点击
for (let i = 0; i < intersects.length; i++) {
//图标点击
if (
intersects[i].object.userData &&
(intersects[i].object.userData.type == 'icon' ||
intersects[i].object.parent.userData.type == 'icon' ||
intersects[i].object.parent.parent.userData.type == 'icon')
) {
if (Map_QM.endModel && Map_QM.endModel.visible) {
Map_QM.endModel.visible = false
}
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].findPath.clearPath()
let buildOrder =
intersects[i].object.userData.buildOrder || intersects[i].object.parent.userData.buildOrder || intersects[i].object.parent.parent.userData.buildOrder || 0
let floorOrder =
intersects[i].object.userData.floorOrder || intersects[i].object.parent.userData.floorOrder || intersects[i].object.parent.parent.userData.floorOrder || 0
let navCode = intersects[i].object.userData.navCode || intersects[i].object.parent.userData.navCode || intersects[i].object.parent.parent.userData.navCode
let src = intersects[i].object.userData.src || intersects[i].object.parent.userData.src || intersects[i].object.parent.parent.userData.src
let facCode = intersects[i].object.userData.facCode || intersects[i].object.parent.userData.facCode || intersects[i].object.parent.parent.userData.facCode
let title = intersects[i].object.userData.title || intersects[i].object.parent.userData.title || intersects[i].object.parent.parent.userData.title
/**
* @api {事件} icon 点击设施图标
* @apiGroup 地图事件
* @apiDescription 用户点击设施图标后触发自定义事件
* @apiVersion 2.0.0
* @apiSampleRequest off
*
* @apiParamExample 请求示例
* Map_QM.addEventListener("icon",onClickIcon,false);
*/
Map_QM.dispatchEvent({
type: 'icon',
data: { buildOrder: buildOrder, floorOrder: floorOrder, node: navCode, src: src, facCode: facCode, title: title }
})
console.log('触发 icon 事件 ', {
type: 'icon',
data: { buildOrder: buildOrder, floorOrder: floorOrder, node: navCode, src: src, facCode: facCode, title: title }
})
return
}
}
for (let i = 0; i < intersects.length; i++) {
//店铺BOX点击
if (intersects[i].object.userData && intersects[i].object.userData.type == "shop") {
if(intersects[i].object.name != ""){
if (Map_QM.endModel && Map_QM.endModel.visible) {
Map_QM.endModel.visible = false;
}
clickShop = true;
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].findPath.clearPath();
Map_QM.setSelectShopMat(intersects[i].object);
break;
}else{ //空店铺有编号
if(intersects[i].object.userData.houseNumber && intersects[i].object.userData.houseNumber != "shop"){
clickOnly = true;
onlyData = intersects[i].object.userData;
}
}
}
}
/**
* @api {事件} shop 点击已绑定品牌的店铺
* @apiGroup 地图事件
* @apiDescription 用户点击店铺后触发自定义事件
* @apiVersion 2.0.0
* @apiSampleRequest off
*
* @apiParamExample 请求示例
* Map_QM.addEventListener("shop",onClickShop,false);
*/
if (clickShop && Map_QM.selectShop && Map_QM.selectShop.userData) {
if (Map_QM.selectShop.userData.shopData.hasOwnProperty('houseNumber')) {
Map_QM.dispatchEvent({
type: 'shop',
data: Map_QM.selectShop.userData
})
} else {
/**
* @api {事件} onlyShop 点击未绑定品牌的店铺
* @apiGroup 地图事件
* @apiDescription 用户点击空店铺后触发自定义事件
* @apiVersion 2.0.0
* @apiSampleRequest off
*
* @apiParamExample 请求示例
* Map_QM.addEventListener("onlyShop",onClickShop,false);
*/
Map_QM.dispatchEvent({
type: 'onlyShop',
data: Map_QM.selectShop.userData
})
}
} else {
if(clickOnly){
Map_QM.dispatchEvent({
type: "onlyShop",
data: onlyData
})
}else{
Map_QM.dispatchEvent({
type: "shop",
data: null
})
}
}
},
/**
* @api {方法} setSelectShopMatByName(shopNum) 设置box 选中
* @apiGroup 地图交互
* @apiDescription 地图box 选中
* @apiVersion 2.0.0
* @apiParam {String} shopNum POI编号
*
* @apiSampleRequest off
*
* @apiParamExample {String} 请求示例
*
* Map_QM.setSelectShopMatByName("L101");
*
*/
setSelectShopMatByName: function (ipName) {
for (let i = 0; i < Map_QM.mapArr[Map_QM.util.selectBuild].length; i++) {
let shopArr = Map_QM.mapArr[Map_QM.util.selectBuild][i].shopObj.children
for (let k = 0; k < shopArr.length; k++) {
if (shopArr[k].name == ipName) {
Map_QM.setSelectShopMat(shopArr[k])
break
}
}
}
},
//改变选中店铺box
setSelectShopMat: function (selObject) {
TweenMax.killAll(true)
if (Map_QM.selectShop) {
Map_QM.selectShop.scale.z = 1
}
Map_QM.parseSelectShop(selObject)
},
updateRender:function(){
Map_QM.controls.update();
Map_QM.renderer.render(Map_QM.scene, Map_QM.camera);
Map_QM.labelRenderer.render(Map_QM.scene, Map_QM.camera);
Map_QM.labelRenderer.renderObject( Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].CSSObj, Map_QM.camera );
Map_QM.labelRenderer.zOrder( Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].labelObj );
},
/**
* 初始化后调用
*/
timeOutInit: function () {
Map_QM.updateRender();
Map_QM.collLabel();
renderCount=0
if (Map_QM.callBackLoadOver) {
let floorData = []
for (let i = 0; i < Map_QM.util.allMap.length; i++) {
let build = []
for (let j = 0; j < Map_QM.util.allMap[i].buildArr.length; j++) {
if (Map_QM.util.allMap[i].buildArr[j]) {
build.push({ order: Map_QM.util.allMap[i].buildArr[j].order, name: Map_QM.util.allMap[i].buildArr[j].name })
}
}
floorData.push(build)
}
if (Map_QM.backObj) {
Map_QM.controls.enabled = true
Map_QM.backObj.data = floorData
}
Map_QM.callBackLoadOver(Map_QM.backObj) //初始化完成后回调
Map_QM.callBackLoadOver = null
Map_QM.backObj = null
}
Map_QM.dispatchEvent({
type: 'changeFloorOver',
data: Map_QM.selectFloor
})
},
autoChangeEleAngle: function () {
if (Map_QM.mapArr[Map_QM.util.selectBuild]) {
for (let m = 0; m < Map_QM.mapArr[Map_QM.util.selectBuild].length; m++) {
if (Map_QM.mapArr[Map_QM.util.selectBuild][m].allObj.visible) {
let svgChilds = Map_QM.mapArr[Map_QM.util.selectBuild][m].svgObj.children;
let rat = Map_QM.controls.getRotateHorizontal();
svgChilds.forEach((item) => {
if (Math.abs(item.rotation.x) < 0.5) {
if ((rat - item.userData.rot) > 1.7 || (rat - item.userData.rot) < -1.7) {
item.rotation.z = item.userData.rot < 0 ? item.userData.rot + 3.1415926 : item.userData.rot - 3.1415926;
} else {
item.rotation.z = item.userData.rot;
}
}
});
let logoChilds = Map_QM.mapArr[Map_QM.util.selectBuild][m].shopObj.children;
logoChilds.forEach((item) => {
if (item.children.length>0) {
item.children.forEach((obj) => {
if (obj.userData.type == "logo") {
if ((rat - obj.userData.rot) > 1.7 || (rat - obj.userData.rot) < -1.7) {
obj.rotation.z = obj.userData.rot < 0 ? obj.userData.rot + 3.1415926 : obj.userData.rot - 3.1415926;
} else {
obj.rotation.z = obj.userData.rot;
}
}
})
}
});
}
}
}
},
disPlayEvent: function (e) {
renderCount=0;
Map_QM.collLabel();
},
/**
* 碰撞检测
* @param {Object} 传入检测楼层下标
*/
controlsChock: function () {
Map_QM.autoChangeEleAngle()
renderCount=0;
/**
* @api {事件} MapAngleChange 地图的方向改变
* @apiGroup 地图事件
* @apiDescription 用户操作地图时触发
* @apiVersion 2.0.0
* @apiSampleRequest off
*
* @apiParamExample 请求示例
* Map_QM.addEventListener("MapAngleChange",onMapAngleChange,false);
*/
Map_QM.dispatchEvent({
type: 'MapAngleChange',
data: { hAngle: Map_QM.controls.getRotateHorizontal(), vAngle: Map_QM.controls.getRotate() }
})
if (Map_QM.util.options.inArea && isJUZ) {
clearTimeout(shopTime);
shopTime = setTimeout(() => {
clearTimeout(shopTime);
isJUZ = false;
Map_QM.controls.setZoom(1)
Map_QM.controls.reset()
Map_QM.util.options.deviceAng && Map_QM.rotationAngle(Map_QM.util.deviceObj.angle)
}, 6000);
}
},
//内部碰撞检测
collLabel: function () {
if (!Map_QM) {
return;
}
if (Map_QM.mapArr[Map_QM.util.selectBuild] && Map_QM.buildObj.visible && Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor]) {
if (Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.visible && (!Map_QM.buildObj.userData.hasOwnProperty("visible") || Map_QM.buildObj.userData.visible)) {
let childs = Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].labelObj.children;
let len = childs.length
for (let i = 0; i < len; i++) {
if(!childs[i].userData.isShow){ //是否可见
continue;
}
let obj = childs[i].element;
if(Map_QM.util.options.collision){
if (obj.style.transform) {
obj.style.display = ""
let labP = obj.getBoundingClientRect()
for (let j = 0; j < i; j++) {
if (childs[j].element.style.display == "") {
let pb = childs[j].element.getBoundingClientRect()
let isCol = Map_QM.util.isCollision(labP, pb)
if (isCol) {
if (!childs[i].userData.mapShow) {
obj.style.display = "none"
break;
} else if (!childs[j].userData.mapShow) {
childs[j].element.style.display = "none"
}
}
}
}
}
}else{
obj.style.display = ""
}
}
}
}
},
/**
* 寻路----------------------------------------------------------------------------------------------------------------------------------------
*/
/**
* @api {方法} bounceIcon({type:"xsj"}) 图标弹跳
* @apiGroup 地图导航
* @apiDescription 地图图标弹跳效果
* @apiVersion 2.0.0
* @apiParam {String} iconType 设施缩写
*
* @apiSampleRequest off
*
* @apiParamExample {String} 请求示例
*
* Map_QM.bounceIcon({type:"xsj"});
*
*/
bounceIcon: function (iconType) {
let toFloor = parseInt(Map_QM.util.selectFloor)
let facs = Map_QM.mapArr[Map_QM.util.selectBuild][toFloor].serObj.children //交通图标
for (let i = 0; i < facs.length; i++) {
if (facs[i].type == 'Object3D') {
facs[i].reSetSite()
if (facs[i].facCode == iconType) {
facs[i].jumpIcon()
}
}
}
},
/**
* @api {方法} pathIcon({type:"xsj"}) 获取最近设施
* @apiGroup 地图导航
* @apiDescription 获取离当前楼层最近的设施
* @apiVersion 2.0.0
* @apiParam {JSON} type 设施缩写
*
* @apiSampleRequest off
*
* @apiParamExample {String} 请求示例
*
* Map_QM.pathIcon({type:"xsj"});
*
* @apiSuccessExample 返回示例
* {
* "floor": 楼层编号, "node": 设施导航点,"typeCode":设施编号
* }
*
*/
pathIcon: function (iconType) {
let selIcon; //
let minS = -1;
if (!Map_QM.util.startObj.build && parseInt(Map_QM.util.startObj.build) != 0) {
Map_QM.util.startObj.build = parseInt(Map_QM.util.deviceObj.build);
}
try{
let startNade = Map_QM.util.startObj.build + "_" + Map_QM.util.startObj.floor + "_" + Map_QM.util.startObj.node;
const costAll = dijkstra.single_source_shortest_paths(Map_QM.util.pathStateObj.graphPath, startNade, startNade).costs;
if (costAll) {
for (let i = 0; i < Map_QM.mapArr[parseInt(Map_QM.util.deviceObj.build)].length; i++) {
let sers = Map_QM.mapArr[parseInt(Map_QM.util.deviceObj.build)][i].serObj.children; //服务图标
for (let n = 0; n < sers.length; n++) {
if (sers[n].userData.facCode == iconType.type || ((iconType.type=="xsjn" || iconType.type=="xsjv") && sers[n].userData.facCode=="xsj")) {
let toNade = sers[n].userData.buildOrder+ "_" + sers[n].userData.floorOrder + "_" + sers[n].userData.navCode;
if (!selIcon) {
minS = costAll[toNade];
if (minS) {
selIcon = sers[n];
}
} else {
let s1 = costAll[toNade];
if (s1 && s1 < minS) {
minS = s1;
selIcon = sers[n];
}
}
}
}
}
if (selIcon) {
return { "build": parseInt(Map_QM.util.deviceObj.build), "floor": selIcon.userData.floorOrder, "site": { x: selIcon.position.x, y: selIcon.position.y }, "node": selIcon.userData.navCode, "no": selIcon.userData.no, "typeCode": Map_QM.util.getFacType(iconType.type) };
} else { // 当前楼栋没有
for (let b = 0; b < Map_QM.mapArr.length; b++) {
if (b != parseInt(Map_QM.util.deviceObj.build)) {
for (let i = 0; i < Map_QM.mapArr[b].length; i++) {
let sers = Map_QM.mapArr[b][i].serObj.children; //服务图标
for (let n = 0; n < sers.length; n++) {
if (sers[n].userData.facCode == iconType.type) {
let toNade = b + "_" + sers[n].userData.floorOrder + "_" + sers[n].userData.navCode;
if (!selIcon) {
minS = costAll[toNade];
if (minS) {
selIcon = sers[n];
selIcon.build = b;
}
} else {
let s1 = costAll[toNade];
if (s1 && s1 < minS) {
minS = s1;
selIcon = sers[n];
selIcon.build = b;
}
}
}
}
}
}
}
if (selIcon) {
return { "build": selIcon.userData.buildOrder, "floor": selIcon.userData.floorOrder, "node": selIcon.userData.navCode, "site": { x: selIcon.position.x, y: selIcon.position.y }, "no": selIcon.userData.no, "typeCode": Map_QM.util.getFacType(iconType.type) };
}
}
}
}catch(e){
console.log(e)
}
},
/**
* @api {方法} pathByStartAndOver(startObj,toObj,callBackFun) 地图路径规划
* @apiGroup 地图导航
* @apiDescription 根据传入的起、终点;直接导航
* @apiVersion 2.0.0
* @apiParam {String} startObj.shopNum 店铺编号/车位编号
* @apiParam {String} startObj.type "shop"/"park"
*
* @apiParam {String} toObj.shopNum 店铺编号/车位编号
* @apiParam {String} toObj.type "shop"/"park"
*
* @apiParam {Function} callBackFun 回调函数
*
* @apiSampleRequest off
*
* @apiParamExample {String} 请求示例
*
* Map_QM.pathByStartAndOver({"shopNum":"L102","type":"shop"},{"shopNum":"L204","type":"shop"});
*
*/
pathByStartAndOver: function (startObj, toObj, callBackFun) {
try {
Map_QM.util.startObj = this.shopNumToNavPoint(startObj, startObj.type)
let overObj = this.shopNumToNavPoint(toObj, toObj.type)
this.pathNode(overObj, callBackFun)
} catch (e) {
return '传入点位无法导航'
}
},
/**
* @api {方法} changeStartPoint() 设置起始点位
* @apiGroup 地图导航
* @apiDescription 设置起始点位
* @apiVersion 2.0.0
* @apiParam {int} build 起点楼栋编号
* @apiParam {int} floor 起点楼层编号
* @apiParam {String} node 起点编号
* @apiParam {int} angle 起点角度
*
* @apiSampleRequest off
*
* @apiParamExample {String} 请求示例
*
* Map_QM.changeStartPoint({"build":0, "floor":3, "node":"20", "angle":0});
*
*/
changeStartPoint: function (toObj) {
this.clearFloor()
for (let i = 0; i < this.mapArr[parseInt(this.util.startObj.build)].length; i++) {
for (let len = this.mapArr[parseInt(this.util.startObj.build)][i].allObj.children.length - 1; len >= 0; len--) {
let obj = this.mapArr[parseInt(this.util.startObj.build)][i].allObj.children[len]
if (obj.userData.type == 'start') {
this.mapArr[parseInt(this.util.startObj.build)][i].allObj.remove(obj)
}
}
}
if (toObj && toObj.node) {
let pathData = this.util.allMap[parseInt(toObj.build)].buildArr[parseInt(toObj.floor)].mapData.path
this.util.startObj.xaxis = pathData.nodes[parseInt(toObj.node)].x
this.util.startObj.yaxis = pathData.nodes[parseInt(toObj.node)].y
this.util.startObj.build = parseInt(toObj.build);
this.util.startObj.floor = parseInt(toObj.floor);
this.util.startObj.node = toObj.node;
this.util.startObj.angle = toObj.angle || 0;
} else {
let pathData = this.util.allMap[parseInt(this.util.deviceObj.build)].buildArr[parseInt(this.util.deviceObj.floor)].mapData.path
pathData.nodes.sort(this.util.sortNode)
this.util.deviceObj.xaxis = pathData.nodes[parseInt(this.util.deviceObj.node)].x
this.util.deviceObj.yaxis = pathData.nodes[parseInt(this.util.deviceObj.node)].y
this.util.startObj = this.util.deviceObj
}
this.mapArr[parseInt(this.util.startObj.build)][parseInt(this.util.startObj.floor)].setStartSite(
this.util.startObj.xaxis,
this.util.startObj.yaxis,
parseInt(this.util.shopHeight)+20
)
},
/**
* @api {方法} changeMapIPState(ipName,color) 改变POI颜色
* @apiGroup 地图交互
* @apiDescription 改变POI 颜色
* @apiVersion 2.0.0
* @apiParam {string} ipName POI名称
* @apiParam {string} color 颜色字符串
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.changeMapIPState("L1001","#ffff00");
*
*/
changeMapIPState: function (ipName, color) { // #775544 #AD8164
for (let i = 0; i < this.mapArr[this.util.selectBuild].length; i++) {
let shopArr = this.mapArr[this.util.selectBuild][i].shopObj.children
for (let k = 0; k < shopArr.length; k++) {
if (shopArr[k].name == ipName || (shopArr[k].userData && shopArr[k].userData.houseNumber == ipName)) {
shopArr[k].userData.initMaterial = shopArr[k].material
shopArr[k].material = this.util.getMeshMaterial(color || 0xeab16e)
break
}
}
}
},
/**
* @api {方法} resetMapIPState(ipName) 恢复POI颜色
* @apiGroup 地图交互
* @apiDescription 恢复POI初始颜色
* @apiVersion 4.0.0
* @apiParam {string} ipName POI名称
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.resetMapIPState("L101");
*
*/
resetMapIPState: function (ipName) {
for (let i = 0; i < this.mapArr[this.util.selectBuild].length; i++) {
let shopArr = this.mapArr[this.util.selectBuild][i].shopObj.children
for (let k = 0; k < shopArr.length; k++) {
if (shopArr[k].name == ipName) {
shopArr[k].material = shopArr[k].userData.initMaterial
break
}
}
}
},
/**
* @api {方法} getMapIPData(ipName) 获取POI 基础数据
* @apiGroup 地图交互
* @apiDescription 获取POI 基础数据
* @apiVersion 2.0.0
* @apiParam {string} ipName POI名称
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.getMapIPData("L1001");
*
* @apiSuccessExample 返回示例
* {
* shopNum:店铺编号, shopName:店铺名 node:导航点, floor:楼层编号, xaxis:中心点X坐标, yaxis:中心点Y坐标, borderColor:边框色, entColor:填充色
* }
*/
getMapIPData: function (ipName) {
for (let i = 0; i < Map_QM.mapArr[Map_QM.util.selectBuild].length; i++) {
let shopArr = Map_QM.mapArr[Map_QM.util.selectBuild][i].shopObj.children
for (let k = 0; k < shopArr.length; k++) {
if (shopArr[k].name == ipName || (shopArr[k].userData && shopArr[k].userData.houseNumber == ipName)) {
return shopArr[k].userData
}
}
}
},
/**
* @api {方法} pathNode() 地图模拟导航
* @apiGroup 地图导航
* @apiDescription 地图路径模拟导航
* @apiVersion 2.0.0
* @apiParam {int} floor 楼层编号
* @apiParam {string} node 路径点位编号
* @apiParam {function} callBackFun 回调方法
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.pathNode({build:0, floor:2,node:"53"},callBackFun);
*
*/
pathNode: function (toObj, callBackFun) {
if (!toObj) {
return { direction: '', wayList: [] }
}
pathCameraState = Map_QM.util.options.pathStyle
Map_QM.reSetGuide();
Map_QM.onShowDeviceSite()
Map_QM.selectShop = null
Map_QM.util.pathStateObj.isPathState = true
Map_QM.elementDestroy("all");
if (!Map_QM.util.startObj.xaxis && !Map_QM.util.startObj.yaxis) {
Map_QM.changeStartPoint(null)
}
Map_QM.util.overObj = null
Map_QM.util.overObj = { build: toObj.build || 0, floor: toObj.floor, node: toObj.node, shopNum: toObj.shopNum }
if (Map_QM.util.overObj.node != '') {
Map_QM.cancelRender()
this.onFindPathModel()
if (callBackFun) {
Map_QM.parseForShopArr()
const data = JSON.parse(JSON.stringify(Map_QM.util.pathStateObj.forShopArr))
callBackFun(data)
}
Map_QM.startRender()
}
},
parseForShopArr: function () {
Map_QM.util.pathStateObj.forShopArr = { direction: '', wayList: [] }
Map_QM.forShopArr.forEach((item, index) => {
if (item.hasOwnProperty('Direction')) {
Map_QM.util.pathStateObj.forShopArr.direction = item.Direction
Map_QM.util.pathStateObj.forShopArr.directionEn = item.DirectionEn
}
if (item.hasOwnProperty('wayShop') && item.wayShop) {
for (let i = 0; i < item.wayShop.length; i++) {
let enTlite = item.wayShop[i].shop.nameEn == '' ? item.wayShop[i].shop.name : item.wayShop[i].shop.nameEn
Map_QM.util.pathStateObj.forShopArr.wayList.push({
isAddPrefix: false,
name: '经过 ' + item.wayShop[i].shop.name,
nameEn: 'PASS ' + enTlite,
logoPath: item.wayShop[i].shop.logoPath,
code: item.wayShop[i].shop.code,
shopNum: item.wayShop[i].shop.houseNumber
})
}
}
if (item.hasOwnProperty('Facilities') && item.Facilities) {
//设施
Map_QM.util.pathStateObj.forShopArr.wayList.push({
isAddPrefix: true,
name: '乘坐 ' + item.Facilities.userData.title + '到 ' + Map_QM.mapArr[Map_QM.util.selectBuild][parseInt(Map_QM.forShopArr[index + 1].floor)].floorName,
nameEn: 'BY ' + item.Facilities.userData.title + 'TO ' + Map_QM.mapArr[Map_QM.util.selectBuild][parseInt(Map_QM.forShopArr[index + 1].floor)].floorName,
logoPath: item.Facilities.imgUrl,
code: ((Math.random() * 0x1234567) | 0).toString(16).substring(0),
shopNum: item.Facilities.userData.facCode + item.Facilities.userData.no
})
}
})
},
/**
* @api {方法} getGapByPathNode() 获取实际距离
* @apiGroup 地图导航
* @apiDescription 通过点位获取距离
* @apiVersion 2.0.0
* @apiParam {int} floor 楼层编号
* @apiParam {string} node 路径点位编号
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.getGapByPathNode({floor:2,node:"53"});
*
* @apiSuccessExample {Object} dist 距离米数 time 步行时间
* {
* dis:200,time:4
* }
*/
getGapByPathNode: function (toObj) {
let startNade = Map_QM.util.deviceObj.build + '_' + Map_QM.util.deviceObj.floor + '_' + Map_QM.util.deviceObj.node
let toNade = toObj.build + '_' + toObj.floor + '_' + toObj.node
let path = { cost: -1 },
minTime = 1
try {
path = dijkstra.find_path(Map_QM.util.pathStateObj.graphPath, startNade, toNade)
minTime = parseInt(path.cost / Map_QM.util.options.mapScale / 50) < 0.5 ? 0.5 : parseInt(path.cost / Map_QM.util.options.mapScale / 50)
console.log(`距离目的地 ${parseInt(path.cost / Map_QM.util.options.mapScale)} 米,预计${mint} 分钟`) // 21 是比例尺
} catch (e) {
console.log(e)
}
return { dis: parseInt(path.cost / Map_QM.util.options.mapScale), time: minTime }
},
/**
* @api {方法} getAllIcon() 获取所有Icon
* @apiGroup 地图数据
* @apiDescription 获取所有Icon
* @apiVersion 2.0.0
* @apiParam {int} floorOrder 楼层编号(默认 所有)
*
* @apiSampleRequest off
*
*/
getAllIcon: function (floorOrder = -1, buildOrder = -1) {
let icons = []
if (floorOrder != -1) {
let bd = buildOrder == -1 ? Map_QM.util.selectBuild : buildOrder
let sers = Map_QM.mapArr[bd][floorOrder].serObj.children //服务图标
for (let n = 0; n < sers.length; n++) {
if (sers[n].type == 'Object3D'&& sers[n].userData.type == "icon") {
let title = sers[n].userData.title || Map_QM.util.getFacName(sers[n].userData.facCode)
let titleEn = Map_QM.util.iconEn[title]
let type = sers[n].userData.facCode
let imgUrl = sers[n].userData.src
if (sers[n].userData.facCode == 'upft' || sers[n].userData.facCode == 'downft' || sers[n].userData.facCode == 'ft') {
if (title == '上扶梯' || title == '下扶梯') {
title = '扶梯'
}
titleEn = Map_QM.util.iconEn[title]
type = 'ft'
}
let icon = { type: type, floor: floorOrder, imgUrl: imgUrl, poid: sers[n].userData.poid, title: title, titleEn: titleEn }
icons.push(icon)
}
}
return icons
}
for (let j = 0; j < Map_QM.mapArr.length; j++) {
let iconBuild = []
for (let i = 0; i < Map_QM.mapArr[j].length; i++) {
let iconArr = []
if (Map_QM.mapArr[j][i].serObj) {
let sers = Map_QM.mapArr[j][i].serObj.children //服务图标
for (let n = 0; n < sers.length; n++) {
if (sers[n].type == 'Object3D' && sers[n].userData.type == "icon") {
let title = sers[n].userData.title || Map_QM.util.getFacName(sers[n].userData.facCode)
let titleEn = Map_QM.util.iconEn[title]
let type = sers[n].userData.facCode
let imgUrl = sers[n].userData.src
if (sers[n].userData.facCode == 'upft' || sers[n].userData.facCode == 'downft' || sers[n].userData.facCode == 'ft') {
title = '扶梯'
titleEn = Map_QM.util.iconEn[title]
type = 'ft'
}
let icon = { type: type, floor: i, imgUrl: imgUrl, poid: sers[n].userData.poid, title: title, titleEn: titleEn }
iconArr.push(icon)
}
}
}
iconBuild.push(iconArr)
}
icons.push(iconBuild)
}
return icons
},
/**
* @api {方法} pathPark() 获取车位点位
* @apiGroup 地图数据
* @apiDescription 获取车位导航点
* @apiVersion 2.0.0
* @apiParam {String} shopNum 车位编号
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.pathPark({shopNum:"B1002"});
*
* @apiSuccessExample 返回示例
* {
* shopNum: 车位编号, node: 导航点, floor: 楼层编号, xaxis: 中心点X坐标, yaxis: 中心点Y坐标
* }
*/
pathPark: function (toObj) {
return this.shopNumToNavPoint(toObj, 'park')
},
/**
* @api {方法} pathShopByName() 获取店铺点位
* @apiGroup 地图数据
* @apiDescription 通过店铺名称获取点位
* @apiVersion 2.0.0
* @apiParam {String} shopName 店铺名称
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.pathShopByName("金拱门");
*
* @apiSuccessExample 返回示例
* {
* shopNum: 店铺编号, node: 导航点, floor: 楼层编号, xaxis: 中心点X坐标, yaxis: 中心点Y坐标, comeIn:店铺多门点
* }
*/
pathShopByName: function (shopName) {
for (let item of Map_QM.util.shopData) {
if (item.name === shopName) {
let toObj = { shopNum: item.houseNumber, node: item.yaxis }
for (let h = 0; h < Map_QM.util.allMap.length; h++) {
let sArr = Map_QM.util.allMap[h].buildArr
for (let i = 0; i < sArr.length; i++) {
let shops = Map_QM.util.allMap[h].buildArr[i].mapData.shopArea
for (let k = 0; k < shops.length; k++) {
if (shops[k].name == toObj.shopNum) {
toObj.floor = i
toObj.build = h
toObj.node = shops[k].shopNav
toObj.xaxis = shops[k].xaxis
toObj.yaxis = shops[k].yaxis
if (shops[k].comeIn) {
toObj.comeIn = shops[k].comeIn
}
return toObj
}
}
}
}
return toObj
}
}
},
/**
* @api {方法} shopNumToNavPoint() 获取导航点位
* @apiGroup 地图导航
* @apiDescription 通过店铺编号或车位获取导航点位
* @apiVersion 2.0.0
* @apiParam {Object} object build,floor,shopNum 楼栋编号,楼层编号,店铺或车位编号
* @apiParam {String} type 店铺或车位标识 "shop" "park"
*
* @apiSampleRequest off
*
* @apiSuccessExample 返回示例
* {
* shopNum: 店铺编号, node: 导航点, floor: 楼层编号, xaxis: 中心点X坐标, yaxis: 中心点Y坐标, comeIn:店铺多门点
* }
*/
shopNumToNavPoint: function (obj, type) {
let shopArr
let reObj = { build: Map_QM.util.selectBuild, node: '', xaxis: '', yaxis: '', floor: '', comeIn: '' }
for (let h = 0; h < Map_QM.util.allMap.length; h++) {
let sArr = Map_QM.util.allMap[h].buildArr
for (let i = 0; i < sArr.length; i++) {
if (type == 'shop') {
shopArr = sArr[i].mapData.shopArea
} else if (type == 'park') {
shopArr = sArr[i].mapData.parkArea
}
for (let k = 0; k < shopArr.length; k++) {
if (shopArr[k].name == obj.shopNum) {
reObj.floor = i
reObj.build = h
reObj.xaxis = shopArr[k].xaxis
reObj.yaxis = shopArr[k].yaxis
reObj.node = shopArr[k].shopNav
reObj.shopNum = obj.shopNum
if (shopArr[k].comeIn) {
reObj.comeIn = shopArr[k].comeIn
}
return reObj
}
}
}
}
},
/**
* 模拟导航获取路线
*/
onFindPathModel: function (usePath = null) {
Map_QM.forShopArr.length = 0
Map_QM.util._indexPathFloor = 0
Map_QM.util.pathStateObj.isPathPlay = true
if (isNaN(parseInt(Map_QM.util.startObj.node)) || parseInt(Map_QM.util.startObj.node) == -1) {
return
}
if (!Map_QM.util.startObj.xaxis) {
let pathData = Map_QM.util.allMap[parseInt(Map_QM.util.startObj.build)].buildArr[parseInt(Map_QM.util.startObj.floor)].mapData.path
Map_QM.util.startObj.xaxis = pathData.nodes[parseInt(Map_QM.util.startObj.node)].x
Map_QM.util.startObj.yaxis = pathData.nodes[parseInt(Map_QM.util.startObj.node)].y
}
if (!usePath) {
usePath = Map_QM.util.pathStateObj.graphPath
}
if (Map_QM.util.overObj.comeIn) {
const costall = dijkstra.single_source_shortest_paths(Map_QM.util.pathStateObj.graphPath, startNade, startNade).costs
if (costall) {
let inArray = Map_QM.util.overObj.comeIn.split(',')
Map_QM.util.overObj.node = Map_QM.getMinCostByArray(Map_QM.util.overObj.floor, inArray, costall)
}
}
let startNade = Map_QM.util.startObj.build + "_" + Map_QM.util.startObj.floor + "_" + Map_QM.util.startObj.node;
let toNade = Map_QM.util.overObj.build + "_" + Map_QM.util.overObj.floor + "_" + Map_QM.util.overObj.node;
let path = dijkstra.find_path(usePath, startNade, toNade);
Map_QM.forShopPath(path.nodes);
},
forShopPath: function (PathPoint) {
let Dir = '向前出发',
index = 0
let DirEn = 'to forward'
this.forShopArr = []
if (PathPoint.length > 1) {
this.forShopArr.push({ build: Map_QM.util.startObj.build, floor: Map_QM.util.startObj.floor, PathPoint: [] })
let pathData
for (let j = 0; j < PathPoint.length; j++) {
let array = PathPoint[j].split('_')
pathData = Map_QM.util.allMap[parseInt(array[0])].buildArr[parseInt(array[1])].mapData.path
if (array[0] == this.forShopArr[index].build) {
if (array[1] == this.forShopArr[index].floor) {
this.forShopArr[index].PathPoint.push(pathData.nodes[parseInt(array[2])])
} else {
if (j > 0) {
this.forShopArr[index].Facilities = this.getFacilIcon(PathPoint[j - 1].split('_'), parseInt(array[0]))
} else {
this.forShopArr[index].Facilities = null
}
this.forShopArr.push({ build: parseInt(array[0]), floor: parseInt(array[1]), PathPoint: [] })
index++
this.forShopArr[index].PathPoint.push(pathData.nodes[parseInt(array[2])])
}
} else {
this.forShopArr.push({ build: parseInt(array[0]), floor: parseInt(array[1]), PathPoint: [] })
index++
this.forShopArr[index].PathPoint.push(pathData.nodes[parseInt(array[2])])
}
}
let dy = 0,
dx = 0,
ang = 0
if (this.forShopArr[0].PathPoint.length > 1) {
if (this.forShopArr[0].PathPoint.length == 2) {
dy = this.forShopArr[0].PathPoint[1].y - this.forShopArr[0].PathPoint[0].y
dx = this.forShopArr[0].PathPoint[1].x - this.forShopArr[0].PathPoint[0].x
} else {
dy = this.forShopArr[0].PathPoint[2].y - this.forShopArr[0].PathPoint[1].y
dx = this.forShopArr[0].PathPoint[2].x - this.forShopArr[0].PathPoint[1].x
}
ang = (Math.atan2(dy, dx) * 180) / Math.PI - Map_QM.util.deviceObj.angle
ang = ang > 180 ? ang - 360 : ang
ang = ang < -180 ? ang + 360 : ang
if (ang < -50 && ang >= -130) {
Dir = '向前出发'
DirEn = 'to forward'
} else if (ang >= -50 && ang < 50) {
Dir = '向右出发'
DirEn = 'to right'
} else if (ang >= 50 && ang < 130) {
Dir = '向后出发'
DirEn = 'to back'
} else {
Dir = '向左出发'
DirEn = 'to left'
}
}
let pLen = Map_QM.forShopArr[Map_QM.forShopArr.length - 1].PathPoint.length
Map_QM.util.overObj.xaxis = Map_QM.forShopArr[Map_QM.forShopArr.length - 1].PathPoint[pLen - 1].x
Map_QM.util.overObj.yaxis = Map_QM.forShopArr[Map_QM.forShopArr.length - 1].PathPoint[pLen - 1].y
if (Map_QM.forShopArr.length > 0) {
// "floor" PathPoint Direction (Facilities)
Map_QM.forShopArr[0].Direction = Dir
Map_QM.forShopArr[0].DirectionEn = DirEn
for (let m = 0; m < Map_QM.forShopArr.length; m++) {
//查找经过店铺
Map_QM.forShopArr[m].wayShop = Map_QM.foreignShop(Map_QM.forShopArr[m].PathPoint, Map_QM.forShopArr[m].build, Map_QM.forShopArr[m].floor, m)
if (Map_QM.util.overObj.build == Map_QM.forShopArr[m].build && Map_QM.util.overObj.floor == Map_QM.forShopArr[m].floor) {
let len = Map_QM.forShopArr[m].wayShop.length
if (Map_QM.forShopArr[m].wayShop[len - 1] && Map_QM.forShopArr[m].wayShop[len - 1].shop.yaxis == Map_QM.util.overObj.node) {
Map_QM.forShopArr[m].wayShop.pop()
}
}
}
/**
* @api {事件} InitPathOver 地图导航状态完成
* @apiGroup 地图事件
* @apiDescription 地图开始导航时触发
* @apiVersion 2.0.0
* @apiSampleRequest off
*
* @apiParamExample 请求示例
* Map_QM.addEventListener("InitPathOver",onInitPathOver,false);
*/
Map_QM.dispatchEvent({
type: 'InitPathOver',
data: Map_QM.forShopArr
})
} else {
console.error('无可行路径,请检查起、终点位')
return
}
this.onFindPathToObj()
}
},
getMinCostByArray: function (floor, array, costall) {
if (!Map_QM.util.startObj) {
Map_QM.changeStartPoint();
}
if (!Map_QM.util.numBuild) {
Map_QM.util.numBuild = 0;
}
let mis = -1, nodeP;
for (let i = 0; i < array.length; i++) {
let toNade = Map_QM.util.numBuild + "_" + floor + "_" + array[i];
let PathPoint = costall[toNade];
if (mis == -1) {
mis = PathPoint;
nodeP = array[i];
} else {
if (mis > PathPoint) {
mis = PathPoint;
nodeP = array[i];
}
}
}
return nodeP;
},
/**
* 途径店铺
*/
foreignShop: function (pathArr, build, cFloor, m) {
let shopList = []
let shops = Map_QM.mapArr[parseInt(build)][parseInt(cFloor)].shopObj.children
for (let n = 0; n < pathArr.length; n++) {
for (let i = 0; i < shops.length; i++) {
if (shops[i].userData && shops[i].userData.type == 'shop' && shops[i].userData.navRecommend) {
if (shops[i].userData.node == pathArr[n].id && shops[i].userData.shopData) {
let data = { pathArrIn: m, pathIndex: n, shop: shops[i].userData.shopData }
shopList.push(data)
break
}
}
}
}
return shopList
},
getFacilIcon: function (fromFArr, build = -1) {
if (build === -1) {
build = Map_QM.util.selectBuild
}
let childs = this.mapArr[build][fromFArr[1]].serObj.children
let selectEle
for (let i = 0; i < childs.length; i++) {
if (childs[i].type == "Object3D" && childs[i].userData.navCode == fromFArr[2] && ("dt,ft,upft,lt,downft".search(childs[i].userData.facCode) != -1)) {
selectEle = { imgUrl: childs[i].userData.src, userData: childs[i].userData, position: { x: childs[i].position.x, y: childs[i].position.y } }
break
}
}
return selectEle
},
/**
* 寻路动画方法
*/
onFindPathToObj: function () {
outTime = -1
Map_QM.util._indexPathFloor = 0
Map_QM.callBackLoadOver = Map_QM.callBackForPathShop //楼层初始化完成后回调
if (pathCameraState == '2D') {
Map_QM.onInnerMeDir()
Map_QM.controls.enabled = false
Map_QM.guide = Map_QM.man_2d
}
Map_QM.changeBuildInner(Map_QM.forShopArr[Map_QM.util._indexPathFloor].build, Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor)
},
/**
* 播放楼层动画完成后
*/
callBackForPathShop: function () {
Map_QM.callBackLoadOver = null
if (Map_QM.util.pathStateObj.isPathState) {
//如果是寻路状态,继续导航
Map_QM.onFindPath()
}
},
/**
* 寻路方法
* @param {Object} startN
* @param {Object} endN
*/
onFindPath: function () {
TweenMax.killAll(true)
if (Map_QM.util.overObj.floor == Map_QM.util.selectFloor && Map_QM.util.overObj.xaxis) {
Map_QM.mapArr[Map_QM.util.overObj.build][Map_QM.util.overObj.floor].setOverSite(
Map_QM.util.overObj.xaxis,
Map_QM.util.overObj.yaxis,
parseInt(Map_QM.util.shopHeight)
)
}else{
Map_QM.endModel && (Map_QM.endModel.visible = false);
Map_QM.endIcon && (Map_QM.endIcon.visible = false);
}
if (Map_QM.forShopArr.length > 0) {
document.addEventListener('pathOver', Map_QM.onFindPathFloor, true)
Map_QM.mapArr[Map_QM.forShopArr[Map_QM.util._indexPathFloor].build][Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor].findPath.clearPath()
Map_QM.mapArr[Map_QM.forShopArr[Map_QM.util._indexPathFloor].build][Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor].findPath.onFindPathAnimation(
Map_QM.forShopArr[Map_QM.util._indexPathFloor].PathPoint
) //传入数组
Map_QM.mapArr[Map_QM.forShopArr[Map_QM.util._indexPathFloor].build][Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor].findPath.guidePathPlay(
Map_QM.forShopArr[Map_QM.util._indexPathFloor]
)
Map_QM.controlsChock()
}
},
/**
* 显示楼层
*/
showNavFloor: function (fromFloor, toFloor, build) {
let floorArr = []
let min = Math.min(fromFloor, toFloor)
let max = Math.max(fromFloor, toFloor)
for (let i = min; i <= max; i++) {
floorArr.push(Map_QM.mapArr[build][i].floorName)
}
if (floorArr.length > 5) {
floorArr.splice(2, floorArr.length - 3)
floorArr[1] = '...'
}
return floorArr
},
//导航完成事件
onFindPathFloor: function (event) {
document.removeEventListener('pathOver', Map_QM.onFindPathFloor)
if (Map_QM.forShopArr.length <= Map_QM.util._indexPathFloor) {
return
}
if (Map_QM.util._indexPathFloor < Map_QM.forShopArr.length - 1) {
//楼层切换
if (Map_QM.forShopArr[Map_QM.util._indexPathFloor].Facilities) {
let pathFloor = Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor
let x0 = Map_QM.forShopArr[Map_QM.util._indexPathFloor].Facilities.position.x + 64
let y0 = Map_QM.forShopArr[Map_QM.util._indexPathFloor].Facilities.position.y
let model = Map_QM.forShopArr[Map_QM.util._indexPathFloor].Facilities.userData.model
/**
* @api {事件} PathPlaying 地图导航的实时状态
* @apiGroup 地图事件
* @apiDescription 地图导航过程中实时触发
* @apiVersion 2.0.0
* @apiSampleRequest off
*
* @apiParamExample 请求示例
* Map_QM.addEventListener("PathPlaying",onPathPlaying,false);
*/
Map_QM.dispatchEvent({
//寻路中返回小人当前所在点位
type: 'PathPlaying',
data: {
shopNum: Map_QM.forShopArr[Map_QM.util._indexPathFloor].Facilities.userData.facCode + Map_QM.forShopArr[Map_QM.util._indexPathFloor].Facilities.userData.no
}
})
let box
if (model && model.userData.name == 'dt') {
model.traverse(function (child) {
if (child.isMesh && child.name == 'zhitibox') {
box = child
}
if (child.isMesh && (child.name == 'zhitijiegou' || child.name == 'zhitiboli')) {
child.scale.y = 7.5
}
})
}
let zo = 2,
tz = 2,
boxT = 0,
boxZ = 0
let add = window.innerWidth>2000 ? 80 : 40;
let lft = window.innerWidth>2000 ? 8 : 4;
Map_QM.util._indexPathFloor++
let toFloor = parseInt(Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor)
Map_QM.util.selectFloor = toFloor
let floorArr = Map_QM.showNavFloor(pathFloor, toFloor, parseInt(Map_QM.forShopArr[Map_QM.util._indexPathFloor].build)) //电梯旁显示的楼层名称
if (pathFloor < toFloor) {
tz = (floorArr.length - 1) * add
boxT = 27
} else {
zo = (floorArr.length - 1) * add
boxZ = 27
}
document.getElementById('moveFloor').style.bottom = zo + 'px'
document.getElementById('moveFloor').style.width = add + 'px'
document.getElementById('moveFloor').style.height = add + 'px'
Map_QM.moveFloorbg.element.style.width = (add+lft) + 'px'
Map_QM.moveFloorbg.element.style.height = floorArr.length * add + 'px'
Map_QM.moveFloorbg.position.set(x0, y0, (floorArr.length * add)/-1)
Map_QM.moveFloorbg.applyMatrix4(Map_QM.mapArr[parseInt(Map_QM.forShopArr[Map_QM.util._indexPathFloor].build)][pathFloor].allObj.matrix)
let floorBox = document.getElementById('floorBox')
while (floorBox.hasChildNodes()) {
floorBox.removeChild(floorBox.firstChild)
}
for (let i = floorArr.length - 1; i >= 0; i--) {
let span2 = document.createElement('span')
span2.style.cssText = 'display: block;color: #000000; text-align: center;'
span2.style.fontSize = '16px'
if ( window.innerWidth>2000) {
span2.style.fontSize = '24px'
}
span2.style.width = (add+lft) + 'px'
span2.style.height = add + 'px'
span2.style.lineHeight = add + 'px'
span2.innerText = floorArr[i]
floorBox.appendChild(span2)
}
TweenMax.fromTo(
'#moveFloor',
1.5,
{ bottom: zo },
{
bottom: tz,
delay: 0.1,
onComplete: function () {
Map_QM.moveFloorbg.element.style.display = "none";
Map_QM.callBackLoadOver = Map_QM.callBackForPathShop //楼层初始化完成后回调
Map_QM.changeFloorInner(Map_QM.forShopArr[Map_QM.util._indexPathFloor].build, Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor)
}
}
)
Map_QM.moveFloorbg.element.style.display = "";
if (box) {
TweenMax.fromTo(
box.position,
1.2,
{ y: boxZ },
{
y: boxT,
delay: 0.2,
onComplete: function () {
box.position.y = 0
model.traverse(function (child) {
if (child.isMesh && (child.name == 'zhitijiegou' || child.name == 'zhitiboli')) {
child.scale.y = 1
}
})
}
}
)
}
if (pathCameraState == '3D') {
let xt = Map_QM.guide.position.x + event.detail.dx * 10
let yt = Map_QM.guide.position.y + event.detail.dy * 10
if (model && model.userData.name == 'upft') {
Map_QM.guide.visible = true
TweenMax.to(Map_QM.guide.position, 1.3, {
x: xt,
y: yt,
z: 50,
onComplete: function () {
Map_QM.guide.visible = false
}
})
}
if (model && model.userData.name == 'downft') {
Map_QM.guide.visible = true
TweenMax.to(Map_QM.guide.position, 1.3, {
x: xt,
y: yt,
z: -50,
onComplete: function () {
Map_QM.guide.visible = false
}
})
}
}
} else {
//楼栋切换
Map_QM.util._indexPathFloor++
Map_QM.callBackLoadOver = Map_QM.callBackForPathShop
Map_QM.changeBuildInner(Map_QM.forShopArr[Map_QM.util._indexPathFloor].build, Map_QM.forShopArr[Map_QM.util._indexPathFloor].floor)
}
} else {
Map_QM.util.startObj = Map_QM.util.deviceObj
/**
* @api {事件} PathPlayOver 地图导航完成
* @apiGroup 地图事件
* @apiDescription 地图导航到达目标点时触发
* @apiVersion 2.0.0
* @apiSampleRequest off
*
* @apiParamExample 请求示例
* Map_QM.addEventListener("PathPlayOver",onPathPlayOver,false);
*/
Map_QM.dispatchEvent({
//寻路完成
type: 'PathPlayOver',
data: 'PathPlayOver'
})
}
},
/**
* 楼层状态清理
*/
clearFloor: function (fIndex = -1, reSet = true) {
isJUZ = false
Map_QM.controls.setZoom(1)
if (fIndex == -1) {
fIndex = Map_QM.util.deviceObj.floor
}
if (Map_QM.selectShop) {
Map_QM.selectShop.scale.z = 1
}
if (Map_QM.endModel && Map_QM.endModel.visible) {
Map_QM.endModel.visible = false
}
if (Map_QM.endIcon && Map_QM.endIcon.visible) {
Map_QM.endIcon.visible = false
}
if (Map_QM.moveFloorbg) {
Map_QM.moveFloorbg.element.style.display = "none"
}
if (reSet) {
//叠层不处理
if (Map_QM.mapArr[Map_QM.util.selectBuild] && Map_QM.mapArr[Map_QM.util.selectBuild].length > 0) {
for (let i = 0; i < Map_QM.mapArr[Map_QM.util.selectBuild].length; i++) {
let child = Map_QM.mapArr[Map_QM.util.selectBuild][i].allObj
for (let k = child.children.length - 1; k >= 0; k--) {
if (child.children[k].name == 'lineDash') {
Map_QM.mapArr[Map_QM.util.selectBuild][i].allObj.remove(child.children[k])
}
}
Map_QM.mapArr[Map_QM.util.selectBuild][i].findPath.clearPath()
}
}
Map_QM.remove_child(Map_QM.dtLineGroup)
}
TweenMax.killAll(true)
},
remove_child: function (remObj) {
if (!remObj) {
return
}
let child_elem = remObj.children
for (let i = child_elem.length - 1; i >= 0; i--) {
if (child_elem[i].children.length > 0) {
Map_QM.remove_child(child_elem[i])
} else {
if (child_elem[i] instanceof THREE.Mesh) {
child_elem[i].geometry.dispose() // 删除几何体
if (child_elem[i].material !== undefined) Map_QM.removeMaterial(child_elem.material) // 删除材质
}
}
if (child_elem[i].name != 'light' && child_elem[i].name != 'dtline') {
remObj.remove(child_elem[i])
}
}
},
removeMaterial: function (material) {
if (Array.isArray(material)) {
for (var i = 0, l = material.length; i < l; i++) {
this.removeMaterialFromRefCounter(material[i])
}
} else {
this.removeMaterialFromRefCounter(material)
}
},
removeMaterialFromRefCounter: function (material) {
var materialsRefCounter = this.materialsRefCounter
if (materialsRefCounter) {
var count = materialsRefCounter.get(material)
count--
if (count === 0) {
materialsRefCounter.delete(material)
delete this.materials[material.uuid]
} else {
materialsRefCounter.set(material, count)
}
}
},
/**
* @api {方法} pathStop() 导航暂停/播放
* @apiGroup 地图导航
* @apiDescription 导航动画暂停/播放
* @apiVersion 2.0.0
*
* @apiSampleRequest off
*
*/
pathStop: function (isPlaying) {
Map_QM.util.pathStateObj.isPathPlay = isPlaying === undefined ? !Map_QM.util.pathStateObj.isPathPlay : isPlaying
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].findPath.pathPlay.isPlay = Map_QM.util.pathStateObj.isPathPlay
},
/**
* @api {方法} pathRePlay() 导航动画重播
* @apiGroup 地图导航
* @apiDescription 导航动画重播
* @apiVersion 2.0.0
*
* @apiSampleRequest off
*
*/
pathRePlay: function () {
clearTimeout(Map_QM.util.timeObj.pathTime)
TweenMax.killAll(true)
if(!Map_QM.util.overObj.node){
return
}
Map_QM.util.timeObj.pathTime = setTimeout(() => {
clearTimeout(Map_QM.util.timeObj.pathTime)
Map_QM.controls.reset()
if (Map_QM.util.overObj && Map_QM.forShopArr[0]) {
Map_QM.util.pathStateObj.isPathPlay = true
Map_QM.clearFloor()
Map_QM.onFindPathToObj()
}
}, 100)
},
/**
* @api {方法} ChangePathByFt() 切换扶梯模式
* @apiGroup 地图导航
* @apiDescription 导航切换扶梯模式
* @apiVersion 2.0.0
*
* @apiParam {function} callBack 回调函数
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.ChangePathByFt(function);
*
*/
ChangePathByFt: function (callBack) {
clearTimeout(Map_QM.util.timeObj.pathTime)
TweenMax.killAll(true)
if(!Map_QM.util.overObj.node || Map_QM.util.isMorePath){
return
}
Map_QM.util.timeObj.pathTime = setTimeout(() => {
clearTimeout(Map_QM.util.timeObj.pathTime)
Map_QM.controls.reset()
if (Map_QM.util.overObj) {
Map_QM.clearFloor()
Map_QM.onFindPathModel(Map_QM.util.pathStateObj.ftPath)
if (callBack) {
Map_QM.parseForShopArr()
const data = JSON.parse(JSON.stringify(Map_QM.util.pathStateObj.forShopArr))
callBack(data)
}
}
}, 100)
},
/**
* @api {方法} ChangePathByDt() 切换电梯模式
* @apiGroup 地图导航
* @apiDescription 导航切换电梯模式
* @apiVersion 2.0.0
*
* @apiParam {function} callBack 回调函数
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.ChangePathByDt(function);
*
*/
ChangePathByDt: function (callBack) {
clearTimeout(Map_QM.util.timeObj.pathTime)
TweenMax.killAll(true)
if(!Map_QM.util.overObj.node || Map_QM.util.isMorePath){
return
}
Map_QM.util.timeObj.pathTime = setTimeout(() => {
clearTimeout(Map_QM.util.timeObj.pathTime)
Map_QM.controls.reset()
if (Map_QM.util.overObj) {
Map_QM.clearFloor()
Map_QM.onFindPathModel(Map_QM.util.pathStateObj.dtPath)
if (callBack) {
Map_QM.parseForShopArr()
const data = JSON.parse(JSON.stringify(Map_QM.util.pathStateObj.forShopArr))
callBack(data)
}
}
}, 100)
},
/**
* @api {方法} ChangePathByGood() 切换最佳模式
* @apiGroup 地图导航
* @apiDescription 导航切换最佳模式
* @apiVersion 2.0.0
*
* @apiParam {function} callBack 回调函数
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.ChangePathByGood(function);
*
*/
ChangePathByGood: function (callBack) {
clearTimeout(Map_QM.util.timeObj.pathTime)
TweenMax.killAll(true)
if(!Map_QM.util.overObj.node || Map_QM.util.isMorePath){
return
}
Map_QM.util.timeObj.pathTime = setTimeout(() => {
clearTimeout(Map_QM.util.timeObj.pathTime)
Map_QM.controls.reset()
if (Map_QM.util.overObj) {
Map_QM.clearFloor()
Map_QM.onFindPathModel(Map_QM.util.pathStateObj.graphPath)
if (callBack) {
Map_QM.parseForShopArr()
const data = JSON.parse(JSON.stringify(Map_QM.util.pathStateObj.forShopArr))
callBack(data)
}
}
}, 100)
},
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
changeDocmentResize: function (e) {
let w = parseInt(Map_QM.ele.clientWidth) || parseInt(window.getComputedStyle(Map_QM.ele, null).getPropertyValue('width'))
let h = parseInt(Map_QM.ele.clientHeight) || parseInt(window.getComputedStyle(Map_QM.ele, null).getPropertyValue('height'))
Map_QM.changeWindowResize(w, h)
},
/**
* @api {方法} changeWindowResize() 窗口变化
* @apiGroup 地图交互
* @apiDescription 窗口变化
* @apiVersion 2.0.0
*
* @apiParam {int} width 窗口宽
* @apiParam {int} height 窗口高
*
* @apiSampleRequest off
*
* @apiParamExample 请求示例
*
* Map_QM.changeWindowResize(1280,1080);
*/
changeWindowResize: function (width, height) {
Map_QM.aspect = width / height
Map_QM.cameraPerspective.aspect = Map_QM.aspect
Map_QM.cameraPerspective.updateProjectionMatrix()
Map_QM.cameraOrtho.left = -150 * Map_QM.aspect
Map_QM.cameraOrtho.right = 150 * Map_QM.aspect
Map_QM.cameraOrtho.top = 150;
Map_QM.cameraOrtho.bottom = -150;
Map_QM.cameraOrtho.updateProjectionMatrix()
Map_QM.renderer.setSize(width, height)
Map_QM.labelRenderer.setSize(width, height)
Map_QM.updateRender();
Map_QM.collLabel();
Map_QM.w = width
Map_QM.h = height
}
}
/**
* @api {方法} init(callBack,options) 地图初始化
* @apiGroup 地图数据
* @apiDescription 初始化地图赋值 Map_QM
* @apiVersion 2.0.0
*
* @apiParam {function} callBack 初始化成功后的回调函数
* @apiParam {object} options 初始化对象
* @apiParam {int} options.build 设备所在楼栋编号 默认值6
* @apiParam {int} options.floor 设备所在楼层编号 默认值 true
* @apiParam {int} options.navPoint 设备导航点 默认值 -1
* @apiParam {int} options.angle 起点设备角度 默认值 0
* @apiParam {string} options.perc_H 弹窗的偏移量 默认值 "-50%";
* @apiParam {string} options.containerId 地图div容器Id 默认值 "mapContainer"
* @apiParam {string} options.playSpeed 动画播放速度 默认值6
* @apiParam {boolean} options.collision 是否支持名称的碰撞检测 默认值 true
* @apiParam {boolean} options.modelIcon 交通设施是否使用模型 默认值 true
* @apiParam {Array} options.otherPath 人为干预的路线 默认值 [];
* @apiParam {int} options.fSpace 双叠层状态下楼层的间距 默认值 500
* @apiParam {uint} options.navColor 途径店铺颜色 默认值 0xEE6A50
* @apiParam {boolean} options.iconName 图标名称是否显示 默认值false
* @apiParam {uint} options.pathColor 导航路径颜色 默认值 0xb47834,
* @apiParam {string} options.pathStyle 导航第一视角 默认值 "2D",
* @apiParam {string} options.shopStyle 店铺显示字段编号(shopNum)名称(shopName) 默认值 "shopName",
* @apiParam {int} options.camZoom 地图显示我的方向状态的放大倍数 默认值 3
* @apiParam {boolean} options.inArea 地图点击后是否聚焦到当前位置 默认值 false
* @apiParam {Array} options.iconUrl 设施库图标 默认值 []
*
* @apiSampleRequest off
* @apiParamExample {String} 请求示例
*
* MainMap_QM.init(callBackLoadOver,{build : 0, floor : 3, navPoint : 7, angle : 0, perc_H : "-50%",containerId : "mapContainer"});
*/
MainMap_QM.init = function (callBack, options) {
if(Map_QM){
Map_QM.cancelRender()
Map_QM.beforeDestroy()
}
Map_QM = new MainMap_QM(callBack, options)
return Map_QM
}
Object.assign(MainMap_QM.prototype, THREE.EventDispatcher.prototype)
//////////////////////////////////////-------------------------------FloorMap
FloorMap_QM = function (bIndex, fIndex, floorName) {
this.Model_QM = new MyModel_QM()
this.facUtil = new Facilities_QM()
this.findPath = new FindPath_QM()
this.logoUtil = new ShopLogo_QM()
this.allObj = new THREE.Group()
this.allObj.name = floorName
this.allObj.rotation.x = Math.PI / -2
this.CSSObj = new THREE.Group()
this.labelObj = new THREE.Group()
this.labelObj.renderOrder = 100
this.floorOrder = fIndex
this.buildOrder = bIndex
this.floorName = floorName
//存第三方
this.otherObj = new THREE.Object3D()
this.allObj.add(this.otherObj)
//存放设施图标
this.serObj = new THREE.Object3D()
//存放车位box
this.parkObj = new THREE.Group()
//标签
this.tagObj = new THREE.Group()
this.tagObj.renderOrder = 100
//存放设施图标
this.svgObj = new THREE.Group()
//店铺
this.shopObj = new THREE.Group()
this.allObj.add(this.shopObj)
this.allObj.add(this.svgObj)
this.allObj.add(this.CSSObj)
this.CSSObj.add(this.serObj)
this.CSSObj.add(this.labelObj)
this.CSSObj.add(this.tagObj)
//标签
this.showTagObj = new THREE.Group()
this.showTagObj.renderOrder = 100
this.CSSObj.add(this.showTagObj)
//线条
this.lineObj = new THREE.Group()
this.lineObj.renderOrder = 100
this.allObj.add(this.lineObj)
this.startIcon
}
FloorMap_QM.prototype = {
initDraw: function () {
this.initFloor()
this.initFacilitie()
this.initStairs()
this.initTextArea()
this.initWall()
this.initDecos()
this.initPark()
this.initModel()
this.initTree() //植树
this.initLogos() //贴图
},
initLogos: function () {
let sopce = this
if (Map_QM.util.logos) {
Map_QM.util.logos.map(item => {
if (item.build == sopce.buildOrder && item.floor == sopce.floorOrder) {
sopce.logoUtil.renderIcon(item, sopce, item.site || 0)
}
})
}
},
initModel: function () {
let sopce = this
if (Map_QM.util.modelArr) {
for (let i = 0; i < Map_QM.util.modelArr.length; i++) {
if (Map_QM.util.modelArr[i].build == this.buildOrder && Map_QM.util.modelArr[i].floor == this.floorOrder) {
new THREE.GLTFLoader().load(Map_QM.util.beforPath + Map_QM.util.modelArr[i].url, function (object) {
//加载路径fbx文件
let mod = object.scene
mod.traverse(function (child) {
if (child.isMesh) {
child.receiveShadow = false
child.castShadow = false
child.userData.opacity = child.material.opacity
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding //贴图需要转换成 线性编码
}
child.material.color.convertGammaToLinear(0.7)
}
})
for (let t = 0; t < Map_QM.util.modelArr[i].list.length; t++) {
let obj = mod.clone()
obj.position.set(Map_QM.util.modelArr[i].list[t].site.x, -1 * Map_QM.util.modelArr[i].list[t].site.y, Map_QM.util.modelArr[i].list[t].site.z)
obj.scale.set(Map_QM.util.modelArr[i].list[t].size.x, Map_QM.util.modelArr[i].list[t].size.y, Map_QM.util.modelArr[i].list[t].size.z)
obj.rotateX(Map_QM.util.modelArr[i].list[t].rot.x * Math.PI / 180)
obj.rotateY(Map_QM.util.modelArr[i].list[t].rot.y * Math.PI / 180)
obj.rotateZ(Map_QM.util.modelArr[i].list[t].rot.z * Math.PI / 180)
sopce.allObj.add(obj)
}
})
}
}
}
if (Map_QM.util.labelIconArr) {
for (let i = 0; i < Map_QM.util.labelIconArr.length; i++) {
if (Map_QM.util.labelIconArr[i].build == this.buildOrder && Map_QM.util.labelIconArr[i].floor == this.floorOrder) {
let SpriteDiv = document.createElement('div')
SpriteDiv.className = Map_QM.util.labelIconArr[i].className
SpriteDiv.innerHTML = Map_QM.util.labelIconArr[i].title
SpriteDiv.dataset.id = Map_QM.util.labelIconArr[i].data.id
SpriteDiv.dataset.x = Map_QM.util.labelIconArr[i].site.x
SpriteDiv.dataset.y = Map_QM.util.labelIconArr[i].site.y
SpriteDiv.dataset.z = Map_QM.util.labelIconArr[i].site.z
let pointLabel = new THREE.CSS2DObject(SpriteDiv)
pointLabel.position.set(Map_QM.util.labelIconArr[i].site.x, -1 * Map_QM.util.labelIconArr[i].site.y, Map_QM.util.labelIconArr[i].site.z)
pointLabel.name = Map_QM.util.labelIconArr[i].title
pointLabel.userData = Map_QM.util.labelIconArr[i].data
pointLabel.userData.site = Map_QM.util.labelIconArr[i].site
pointLabel.userData.mapShow = true
pointLabel.userData.isShow = true
pointLabel.userData.type = "icon"
if (Map_QM.util.labelIconArr[i].click) {
//可点击
SpriteDiv.addEventListener(
'click',
event => {
Map_QM.dispatchEvent({
type: 'labelIcon',
data: event.target.dataset
})
},
false
)
} else {
pointLabel.element.style.pointerEvents = 'none'
}
pointLabel.userData.floor = Map_QM.util.labelIconArr[i].floor
sopce.showTagObj.add(pointLabel)
}
}
}
},
initTree: function () {
let mapData = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
if (mapData.models) {
for (let t = 0; t < mapData.models.length; t++) {
for (let i = 0; i < Map_QM.util.fbxModels.length; i++) {
if (mapData.models[t].type == Map_QM.util.fbxModels[i].key) {
let obj = Map_QM.util.fbxModels[i].obj.scene.clone()
obj.position.set(mapData.models[t].x, -1 * mapData.models[t].y, mapData.models[t].site)
obj.scale.set(mapData.models[t].scale, mapData.models[t].scale, mapData.models[t].scale)
obj.rotateX(Map_QM.util.fbxModels[i].operation.rot.x)
obj.rotateY(-1 * mapData.models[t].angle * Math.PI / 180)
obj.renderOrder = 100
for (let k = 0; k < Map_QM.util.fbxModels[i].obj.animations.length; k++) {
let mixer = new THREE.AnimationMixer(obj)
mixer.clipAction(Map_QM.util.fbxModels[i].obj.animations[k]).play()
Map_QM.mixers.push(mixer)
}
//加载编辑器动画
obj.name = mapData.models[t].name
if (mapData.animations) {
mapData.animations.forEach((item)=>{
if(mapData.models[t].name == item.name){
let posArr = [], rotArr = [], scaleArr = [], keyArr = [], proArr = [], clip
item.frames.forEach((it)=>{
keyArr.push(it.time)
posArr.push(it.pos.x, -1*it.pos.y, it.pos.z)
rotArr.push(it.rot/-180*Math.PI)
scaleArr.push(it.size,it.size,it.size)
proArr.push(it.pro)
});
if(item.isType){ //特殊模型动画
let rotKF = new THREE.KeyframeTrack(item.sonName, keyArr, proArr)
clip = new THREE.AnimationClip(item.name, keyArr[keyArr.length-1], [rotKF])
}else{
let posKF = new THREE.KeyframeTrack(item.name+'.position', keyArr, posArr)
let rotKF = new THREE.KeyframeTrack(item.name+'.rotation[y]', keyArr, rotArr)
let scalKF = new THREE.KeyframeTrack(item.name+'.scale', keyArr, scaleArr)
clip = new THREE.AnimationClip(item.name, keyArr[keyArr.length-1], [posKF, rotKF, scalKF])
}
if(clip){
let mixer = new THREE.AnimationMixer(obj)
mixer.clipAction(clip).play()
Map_QM.mixers.push(mixer)
}
}
})
}
this.allObj.add(obj)
}
}
}
}
},
//初始化单楼层
initFloor: function () {
let floor
let mapData = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
let entColor, borderColor
if (mapData.floorArea) {
floor = Map_QM.util.changeAreaToString(mapData.floorArea)
}
let bLen = mapData.buildArea.length
let hLen = mapData.hollowArea.length
let hows_f = []
for (let m = 0; m < hLen; m++) {
let isIn = Map_QM.util.checkAreaInArea(mapData.hollowArea[m], mapData.floorArea);
if(isIn){
hows_f.push(Map_QM.util.changeAreaToString(mapData.hollowArea[m]));
}
}
if (floor) {
entColor = mapData.floorArea.entColor
borderColor = mapData.floorArea.borderColor
floorH = parseInt(mapData.floorArea.toHeight)
let mash = this.Model_QM.MyModelShape(floor, hows_f, mapData.floorArea, entColor, borderColor, 10 + 100 * this.floorOrder);
mash.receiveShadow = true
mash.castShadow = false
mash.userData = {
type: 'floor',
order: this.floorOrder
}
mash.userData.opacity = mapData.floorArea.alphaModle / 100 || 0
mash.name = 'floor'
this.allObj.add(mash)
}
/////////////////////初始化楼栋
for (let i = 0; i < bLen; i++) {
let build = Map_QM.util.changeAreaToString(mapData.buildArea[i])
let hows = []
for (let t = 0; t < hLen; t++) {
let isIn = Map_QM.util.checkAreaInArea(mapData.hollowArea[t], mapData.buildArea[i])
if (isIn) {
hows.push(Map_QM.util.changeAreaToString(mapData.hollowArea[t]))
}
}
entColor = mapData.buildArea[i].entColor
borderColor = mapData.buildArea[i].borderColor
buildH = parseInt(mapData.buildArea[i].toHeight)
let mash = this.Model_QM.MyPlaneShape(build, hows, mapData.buildArea[i], entColor, borderColor, 30 + 100 * this.floorOrder)
mash.receiveShadow = true
mash.castShadow = false
mash.userData = {
type: 'build',
order: this.floorOrder,
xaxis: mapData.buildArea[i].xaxis,
yaxis: mapData.buildArea[i].yaxis
}
mash.userData.opacity = mapData.buildArea[i].alphaModle / 100 || 0
mash.name = mapData.buildArea[i].name;
this.allObj.add(mash)
}
//店铺
let sLen = mapData.shopArea.length
let show = (showE = '')
let showLeb = ''
let logo = '',
navRecommend = false,
shopD = {},
type = 'deco'
let shopData = Map_QM.util.shopData
for (let i = 0; i < sLen; i++) {
if (Map_QM.util.changeAreaToString(mapData.shopArea[i]) != '') {
let arr = Map_QM.util.changeShopLinesToString(mapData.shopArea[i])
entColor = mapData.shopArea[i].entColor || '#b79266'
borderColor = mapData.shopArea[i].borderColor || '#b79266'
show = showE = mapData.shopArea[i].name
logo = ''
showLeb = ''
navRecommend = false
mapShow = false
shopD = {}
if (shopData) {
for (let h = 0; h < shopData.length; h++) {
let houseNum = shopData[h].houseNumber
if (houseNum == mapData.shopArea[i].name) {
show = shopData[h].shopName || shopData[h].name
showLeb = houseNum
showE = shopData[h].shopNameEn || shopData[h].nameEn
logo = shopData[h].logoPath || shopData[h].logoUrl
mapShow = shopData[h].mapShow ?? false
if (shopData[h].navRecommend || shopData[h].isPass) {
navRecommend = shopData[h].navRecommend || shopData[h].isPass
} else {
navRecommend = false
}
shopD = shopData[h]
if (shopData[h].isNewStore) {
//新店
mapData.shopArea[i].type = 'new-shop'
this.addTagLabel(mapData.shopArea[i], { node: mapData.shopArea[i].shopNav, floor: this.floorOrder, build: this.buildOrder })
}
if (shopData[h].activityList && shopData[h].activityList.length > 0) {
//促销
mapData.shopArea[i].type = 'promotion'
this.addTagLabel(mapData.shopArea[i], { node: mapData.shopArea[i].shopNav, floor: this.floorOrder, build: this.buildOrder })
}
shopData[h].color&& (entColor = shopData[h].color)
shopData[h].formatColor&& (entColor = shopData[h].formatColor)
shopData[h].borderColor &&(borderColor = shopData[h].borderColor)
break
}
}
}
let hollShop = []
if (mapData.shopArea[i].hollArea) {
for (let k = 0; k < mapData.shopArea[i].hollArea.length; k++) {
hollShop.push(Map_QM.util.changeAreaToString(mapData.shopArea[i].hollArea[k]))
}
}
let mahc = this.Model_QM.MyModelShape(arr, hollShop, mapData.shopArea[i], entColor, borderColor, 100)
mahc.node = mapData.shopArea[i].shopNav
mahc.userData = {
shopData: shopD,
xaxis: mapData.shopArea[i].xaxis >> 0,
yaxis: mapData.shopArea[i].yaxis >> 0,
node: mahc.node,
floor: this.floorOrder,
build: this.buildOrder,
navRecommend: navRecommend,
type: 'shop',
entColor: entColor,
shopNum: mapData.shopArea[i].name,
shopName: show,
logo: logo,
borderColor: borderColor
}
mahc.userData.opacity = mapData.shopArea[i].alphaModle / 100 || 0
mahc.name = showLeb
mahc.xaxis = mapData.shopArea[i].xaxis >> 0
mahc.yaxis = mapData.shopArea[i].yaxis >> 0
this.shopObj.add(mahc)
if (mapData.shopArea[i].logoUrl && mapData.shopArea[i].isLabel == 0) {
//添加logo
this.logoUtil.renderIcon(mapData.shopArea[i], mahc, parseInt(mapData.shopArea[i].toHeight) + parseInt(mapData.shopArea[i].site || 0) + 1)
} else {
//添加文字
let some = false
if (Map_QM.util.options.boxShop.length && Map_QM.util.options.boxShop[0] !== '') {
some = Map_QM.util.options.boxShop.some(item => {
return mapData.shopArea[i].name.includes(item)
})
}
if (showLeb != '' || some) {
let shopDiv = document.createElement('div')
shopDiv.style.cssText = css_LR
if(window.innerWidth>2000){
shopDiv.style.height = "20px"
shopDiv.style.fontSize = "18px"
}
shopDiv.innerHTML = Map_QM.util.options.shopStyle == "shopName" ? show : mapData.shopArea[i].name;
shopDiv.dataset.name = show
shopDiv.dataset.nameEn = showE
shopDiv.style.display = "none"
let shopLabel = new THREE.CSS2DObject(shopDiv)
shopLabel.position.set(mapData.shopArea[i].xaxis >> 0, -1 * mapData.shopArea[i].yaxis >> 0, parseInt(mapData.shopArea[i].toHeight) + parseInt(mapData.shopArea[i].site || 0));
shopLabel.name = mapData.shopArea[i].name
shopLabel.userData.mapShow = mapShow //是否永久显示
shopLabel.userData.isShow = true
this.labelObj.add(shopLabel)
}
}
}
}
},
addTagLabel: function (obj, userData) {
let shopDiv = document.createElement('img')
shopDiv.src = Map_QM.util.beforPath + "static/img/" + obj.type + ".png"
shopDiv.style.zIndex = 200
shopDiv.style.width = "3.125vw"
let shopLabel = new THREE.CSS2DObject(shopDiv)
shopLabel.userData = userData
shopLabel.userData.mapShow = true //是否永久显示
shopLabel.userData.isShow = false
shopLabel.userData.type = obj.type
shopLabel.position.set(obj.xaxis >> 0, -1 * obj.yaxis >> 0, Map_QM.util.shopHeight+30)
this.tagObj.add(shopLabel)
},
//初始化服务图标
initFacilitie: function () {
let serArr = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData.icons
for (let i = 0; i < serArr.length; i++) {
if (serArr[i].hasOwnProperty('iShow')) {
if (serArr[i].iShow) {
serArr[i].floorOrder = this.floorOrder
serArr[i].buildOrder = this.buildOrder
this.facUtil.renderIcon(serArr[i], this)
}
} else {
serArr[i].floorOrder = this.floorOrder
serArr[i].buildOrder = this.buildOrder
this.facUtil.renderIcon(serArr[i], this)
}
}
},
//初始化电梯图标
initStairs: function () {
let facArr = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData.stairs
for (let i = 0; i < facArr.length; i++) {
if (facArr[i].facCode == 'ft') {
if (Map_QM.util.pathStateObj.elevatorDown && Map_QM.util.pathStateObj.elevator) {
if (facArr[i].downState) {
//上扶梯
let ex = Map_QM.util.pathStateObj.elevator.clone()
ex.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site || 0)
ex.rotation.y = ((facArr[i].angle || 0) * Math.PI) / -180
ex.userData.type = 'icon'
ex.userData.use = '3d'
ex.userData.name = 'upft'
ex.userData.buildOrder = facArr[i].buildOrder
ex.userData.floorOrder = facArr[i].floorOrder
ex.userData.navCode = facArr[i].navCode
ex.userData.src = 'static/img/ft.png'
ex.userData.facCode = facArr[i].facCode
ex.userData.title = facArr[i].title
this.serObj.add(ex)
facArr[i].facCode = 'ft'
this.facUtil.renderIcon(facArr[i], this, false, ex)
} else if (facArr[i].upState) {
//下扶梯
let ex = Map_QM.util.pathStateObj.elevatorDown.clone()
ex.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site || 0)
ex.rotation.y = ((facArr[i].angle || 0) * Math.PI) / -180
ex.userData.type = 'icon'
ex.userData.use = '3d'
ex.userData.name = 'downft'
ex.userData.buildOrder = facArr[i].buildOrder
ex.userData.floorOrder = facArr[i].floorOrder
ex.userData.navCode = facArr[i].navCode
ex.userData.src = 'static/img/ft.png'
ex.userData.facCode = facArr[i].facCode
ex.userData.title = facArr[i].title
this.serObj.add(ex)
facArr[i].facCode = 'ft'
this.facUtil.renderIcon(facArr[i], this, false, ex)
} else {
this.facUtil.renderIcon(facArr[i], this, true)
}
} else {
this.facUtil.renderIcon(facArr[i], this, true)
}
} else if (facArr[i].facCode == 'upft') {
if (Map_QM.util.pathStateObj.elevator) {
let ex = Map_QM.util.pathStateObj.elevator.clone()
ex.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site || 0)
ex.rotation.y = ((facArr[i].angle || 0) * Math.PI) / -180
ex.userData.type = 'icon'
ex.userData.use = '3d'
ex.userData.name = 'upft'
ex.userData.buildOrder = facArr[i].buildOrder
ex.userData.floorOrder = facArr[i].floorOrder
ex.userData.navCode = facArr[i].navCode
ex.userData.src = 'static/img/ft.png'
ex.userData.facCode = facArr[i].facCode
ex.userData.title = facArr[i].title
this.serObj.add(ex)
facArr[i].facCode = 'ft'
this.facUtil.renderIcon(facArr[i], this, false, ex)
} else {
facArr[i].facCode = 'ft'
this.facUtil.renderIcon(facArr[i], this, true)
}
} else if (facArr[i].facCode == 'downft') {
if (Map_QM.util.pathStateObj.elevatorDown) {
let ex = Map_QM.util.pathStateObj.elevatorDown.clone()
ex.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site || 0)
ex.rotation.y = ((facArr[i].angle || 0) * Math.PI) / -180
ex.userData.type = 'icon'
ex.userData.use = '3d'
ex.userData.name = 'downft'
ex.userData.buildOrder = facArr[i].buildOrder
ex.userData.floorOrder = facArr[i].floorOrder
ex.userData.navCode = facArr[i].navCode
ex.userData.src = 'static/img/ft.png'
ex.userData.facCode = facArr[i].facCode
ex.userData.title = facArr[i].title
this.serObj.add(ex)
facArr[i].facCode = 'ft'
this.facUtil.renderIcon(facArr[i], this, false, ex)
} else {
facArr[i].facCode = 'ft'
this.facUtil.renderIcon(facArr[i], this, true)
}
} else if (facArr[i].facCode == 'dt') {
if (Map_QM.util.pathStateObj.straight) {
let stra = Map_QM.util.pathStateObj.straight.clone()
stra.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site || 0)
stra.rotation.y = ((facArr[i].angle || 0) * Math.PI) / -180
stra.userData.type = 'icon'
stra.userData.use = '3d'
stra.userData.name = 'dt'
stra.userData.buildOrder = facArr[i].buildOrder
stra.userData.floorOrder = facArr[i].floorOrder
stra.userData.navCode = facArr[i].navCode
stra.userData.src = 'static/img/dt.png'
stra.userData.facCode = facArr[i].facCode
stra.userData.title = facArr[i].title
this.serObj.add(stra)
this.facUtil.renderIcon(facArr[i], this, false, stra)
} else {
this.facUtil.renderIcon(facArr[i], this, true)
}
} else {
this.facUtil.renderIcon(facArr[i], this, true)
}
}
},
//初始化装饰图标
initDecos: function () {
let mapData = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
let sLen = mapData.decos.length
let entColor, borderColor
if (mapData.groupArea) {
for (let k = 0; k < mapData.groupArea.length; k++) {
var gp = new THREE.Group()
gp.rotateX((mapData.groupArea[k].angleX * Math.PI) / 180)
gp.rotateY((mapData.groupArea[k].angleY * Math.PI) / 180)
gp.rotateZ((mapData.groupArea[k].angleZ * Math.PI) / 180)
for (let i = 0; i < sLen; i++) {
if (mapData.decos[i].gid && mapData.decos[i].gid == mapData.groupArea[k]._name && Map_QM.util.changeAreaToString(mapData.decos[i]) != '') {
let arr = Map_QM.util.changeAreaToString(mapData.decos[i])
entColor = mapData.decos[i].entColor
borderColor = mapData.decos[i].borderColor
let show = mapData.decos[i].name == 'deco' ? '' : mapData.decos[i].name
let hollShop = []
if (mapData.decos[i].hollArea) {
for (let k = 0; k < mapData.decos[i].hollArea.length; k++) {
hollShop.push(Map_QM.util.changeAreaToString(mapData.decos[i].hollArea[k]))
}
}
let mahc = this.Model_QM.MyModelShape(arr, hollShop, mapData.decos[i], entColor, borderColor, 240)
mahc.xaxis = mapData.decos[i].xaxis >> 0
mahc.yaxis = mapData.decos[i].yaxis >> 0
mahc.node = mapData.decos[i].shopNav
mahc.userData = {
type: 'deco',
name: show
}
mahc.userData.opacity = mapData.decos[i].alphaModle / 100 || 0
gp.add(mahc)
mahc.position.x = -1 * mapData.groupArea[k].xaxis
mahc.position.y = mapData.groupArea[k].yaxis
}
}
this.allObj.add(gp)
gp.position.x = mapData.groupArea[k].xaxis
gp.position.y = -1 * mapData.groupArea[k].yaxis
gp.position.z = mapData.groupArea[k].site || 0
gp.scale.set(mapData.groupArea[k].scale, mapData.groupArea[k].scale, mapData.groupArea[k].scale)
}
}
for (let i = 0; i < sLen; i++) {
let arr = Map_QM.util.changeAreaToString(mapData.decos[i])
if (!mapData.decos[i].gid && arr.length>0) {
entColor = mapData.decos[i].entColor
borderColor = mapData.decos[i].borderColor
let show = mapData.decos[i].name == 'deco' ? '' : mapData.decos[i].name
let hollShop = []
if (mapData.decos[i].hollArea) {
for (let k = 0; k < mapData.decos[i].hollArea.length; k++) {
hollShop.push(Map_QM.util.changeAreaToString(mapData.decos[i].hollArea[k]))
}
}
let mahc = this.Model_QM.MyModelShape(arr, hollShop, mapData.decos[i], entColor, borderColor, 70 + 100 * this.floorOrder);
mahc.userData = {
"type": "deco",
"node": mapData.decos[i].shopNav,
"xaxis": mapData.decos[i].xaxis,
"yaxis": mapData.decos[i].yaxis,
"houseNumber": mahc.name,
"name": show
};
this.allObj.add(mahc)
}
}
},
/**
* 渲染墙体
*/
initWall: function () {
let mapData = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
//渲染
if (mapData.wallArea) {
let sLen = mapData.wallArea.length
for (let i = 0; i < sLen; i++) {
let arr = Map_QM.util.changeWallToString(mapData.wallArea[i])
let mahc = this.Model_QM.MyModelShape(
arr,
null,
mapData.wallArea[i],
mapData.wallArea[i].entColor || '#eaeaea',
mapData.wallArea[i].borderColor || '#eaeaea',
300
)
mahc.userData = {
type: 'wall'
}
mahc.userData.opacity = mapData.wallArea[i].alphaModle / 100 || 0
this.allObj.add(mahc)
}
}
},
/**
* 渲染文本
*/
initTextArea: function () {
let mapData = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
//渲染
if (mapData.svgArea) {
let sLen = mapData.svgArea.length
for (let i = 0; i < sLen; i++) {
let mahc = this.Model_QM.MyModelText(mapData.svgArea[i])
mahc.userData = {
type: 'svg',
rot: mahc.rotation.z,
shopNum: mapData.svgArea[i].name
}
this.svgObj.add(mahc)
}
}
},
/**
* 设置终点图标
*/
setOverSite: function (shopX, shopY, shopZ) {
if (Map_QM.endModel) {
Map_QM.endModel.visible = pathCameraState == "2D" ? false : true;
Map_QM.endModel.scale.x = Map_QM.endModel.scale.y = Map_QM.endModel.scale.z = 100;
Map_QM.endModel.position.set(shopX, shopZ, shopY); //x,z,y
Map_QM.endModel.applyMatrix4(Map_QM.sceneGap.matrix);
if (Map_QM.endIcon) {
Map_QM.endIcon.visible = pathCameraState == "2D" ? true : false;
Map_QM.endIcon.scale.x = 100;
Map_QM.endIcon.scale.y = 120;
Map_QM.endIcon.position.set(shopX, 100, shopY); //x,z,y
Map_QM.endIcon.applyMatrix4(Map_QM.sceneGap.matrix);
}
} else {
try {
Map_QM.scene.traverse(item => {
if (item.name == "Z-model") {
Map_QM.scene.remove(item);
}
});
} catch (e) {
console.log("traverse")
}
let loader2 = new THREE.GLTFLoader();
loader2.load(Map_QM.util.beforPath + "static/img/zhong.glb", function (collada2) {
collada2.scene.scale.x = collada2.scene.scale.y = collada2.scene.scale.z = 100;
if (shopX != 0 && shopY != 0) {
collada2.scene.position.set(shopX, shopZ, shopY); //x,z,y
}
collada2.scene.applyMatrix4(Map_QM.sceneGap.matrix);
collada2.scene.renderOrder = 200;
collada2.scene.traverse(function (child) {
if (child.type === "Mesh") {
child.castShadow = Map_QM.util.options.shadow;
child.receiveShadow = Map_QM.util.options.shadow;
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding; //贴图需要转换成 线性编码
}
}
});
for (let k = 0; k < collada2.animations.length; k++) {
let mixer = new THREE.AnimationMixer(collada2.scene)
mixer.clipAction(collada2.animations[k]).play()
Map_QM.mixers.push(mixer)
}
collada2.scene.name = "Z-model";
Map_QM.endModel = collada2.scene;
Map_QM.scene.add(collada2.scene);
Map_QM.endModel.visible = pathCameraState == "2D" ? false : true;
});
let spriteMap = new THREE.TextureLoader().load(Map_QM.util.beforPath + "static/img/Z.png");
let spriteMaterial = new THREE.SpriteMaterial({ //sizeAttenuation: false 禁止跟随鼠标缩放
map: spriteMap,
depthTest: true,
transparent: true,
alphaTest: 0.5
});
Map_QM.endIcon = new MySprite_QM(spriteMaterial);
Map_QM.endIcon.scale.set(100, 120, 1);
Map_QM.endIcon.center = new THREE.Vector2(0.5, 0);
Map_QM.endIcon.position.set(shopX, 100, shopY);
Map_QM.endIcon.applyMatrix4(Map_QM.sceneGap.matrix);
Map_QM.endIcon.renderOrder = 300;
Map_QM.endIcon.name = "Z-model";
Map_QM.endIcon.visible = pathCameraState == "2D" ? true : false;
Map_QM.scene.add(Map_QM.endIcon);
}
},
/**
* 设置起点图标
*/
setStartSite: function (shopX, shopY, shopZ) {
let _this = this;
if (Map_QM.devModel) {
Map_QM.devModel.position.set(shopX, -1 * shopY,50);
_this.allObj.add(Map_QM.devModel)
Map_QM.qiModel.position.set(shopX, -1 * shopY,10);
_this.allObj.add(Map_QM.qiModel)
Map_QM.qiIcon.position.set(shopX, -1 * shopY, shopZ);
_this.allObj.add(Map_QM.qiIcon)
} else {
new THREE.GLTFLoader().load(Map_QM.util.beforPath + "static/img/guide.glb", function (obj) {
obj.scene.scale.x = obj.scene.scale.y = obj.scene.scale.z = 100;
obj.scene.rotation.x = Math.PI / 2;
obj.scene.rotation.y = Map_QM.util.deviceObj.angle*Math.PI/-180;
obj.scene.traverse(function (child) {
if (child.type === "Mesh") {
child.castShadow = Map_QM.util.options.shadow;
child.receiveShadow = Map_QM.util.options.shadow;
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding; //贴图需要转换成 线性编码
}
}
});
if (shopX != 0 && shopY != 0) {
obj.scene.position.set(shopX, -1 * shopY, 50); //x,z,y
}
for (let k = 0; k < obj.animations.length; k++) {
let mixer = new THREE.AnimationMixer(obj.scene)
mixer.clipAction(obj.animations[k]).play()
Map_QM.mixers.push(mixer)
}
Map_QM.devModel = obj.scene;
Map_QM.devModel.renderOrder = 160;
_this.allObj.add(Map_QM.devModel);
});
new THREE.GLTFLoader().load(Map_QM.util.beforPath + "static/img/qi.glb", function (collada) {
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = 100;
collada.scene.rotateX(Math.PI / 2);
collada.scene.visible =false;
collada.scene.traverse(function (child) {
if (child.type === "Mesh") {
child.castShadow = Map_QM.util.options.shadow;
child.receiveShadow = Map_QM.util.options.shadow;
if (child.material.map) {
child.material.map.encoding = THREE.LinearEncoding; //贴图需要转换成 线性编码
}
}
});
if (shopX != 0 && shopY != 0) {
collada.scene.position.set(shopX, -1 * shopY, parseInt(Map_QM.util.buildHeight) + 5); //x,z,y
}
for (let k = 0; k < collada.animations.length; k++) {
let mixer = new THREE.AnimationMixer(collada.scene)
mixer.clipAction(collada.animations[k]).play()
Map_QM.mixers.push(mixer)
}
collada.scene.renderOrder = 200;
collada.scene.userData.type = "start";
Map_QM.qiModel = collada.scene;
_this.allObj.add(collada.scene);
//--------------------------------------------------------------
let spriteMap = new THREE.TextureLoader().load(Map_QM.util.beforPath + "static/img/Q.png");
let spriteMaterial = new THREE.SpriteMaterial({ //sizeAttenuation: false 禁止跟随鼠标缩放
map: spriteMap,
depthTest: true,
transparent: true,
alphaTest: 0.5
});
Map_QM.qiIcon = new MySprite_QM(spriteMaterial);
Map_QM.qiIcon.scale.set(100, 120, 1);
Map_QM.qiIcon.center = new THREE.Vector2(0.5, 0);
Map_QM.qiIcon.position.set(shopX, -1 * shopY, shopZ + 50);
Map_QM.qiIcon.renderOrder = 500;
Map_QM.qiIcon.visible = false;
Map_QM.qiIcon.userData.type = "start";
_this.allObj.add(Map_QM.qiIcon);
});
}
},
/**
* 查找线
* @param {Object} startNode
* @param {Object} endNode
*/
isNoFindLine: function (startNode, endNode) {
let no = false
for (let i = 0; i < startNode.lineArr.length; i++) {
if (startNode.lineArr[i].nextNode.id == endNode.id || startNode.lineArr[i].selfNode.id == endNode.id) {
no = true
break
}
}
return no
},
//初始化停车位
initPark: function () {
let mapData = Map_QM.util.allMap[this.buildOrder].buildArr[this.floorOrder].mapData;
//渲染车位
if (mapData.parkArea) {
let sLen = mapData.parkArea.length;
if (sLen > 0) {
this.allObj.add(this.parkObj);
}
let shapeArr = [], materials = [], parkHeight = 1, borderColor = 0xaaaaaa;
for (let i = 0; i < sLen; i++) {
let arr = Map_QM.util.changeParkToString(mapData.parkArea[i]);
if (arr != "") {
parkHeight = Math.max(parseInt(mapData.parkArea[i].toHeight), parkHeight);
borderColor = mapData.parkArea[i].borderColor;
if (arr.length > 0) {
let shape = new THREE.Shape();
shape.moveTo(arr[0][0], -1 * arr[0][1]);
for (let k = 1; k < arr.length; k++) {
shape.lineTo(arr[k][0], -1 * arr[k][1]);
}
shapeArr.push(shape);
let meshMaterial;
let color2 = new THREE.Color(mapData.parkArea[i].entColor);
for (let e = 0; e < Map_QM.util.parkMaterialArr.length; e++) {
if (Map_QM.util.parkMaterialArr[e].color.equals(color2)) {
meshMaterial = Map_QM.util.parkMaterialArr[e];
}
}
if (!meshMaterial) {
meshMaterial = new THREE.MeshBasicMaterial({
color: mapData.parkArea[i].entColor
});
Map_QM.util.parkMaterialArr.push(meshMaterial);
}
materials.push(meshMaterial);
if (mapData.parkArea[i].childArea && mapData.parkArea[i].childArea.length > 0) {
for (let m = 0; m < mapData.parkArea[i].childArea.length; m++) {
let meshMaterial0;
if (mapData.parkArea[i].childArea[m].color && mapData.parkArea[i].childArea[m].color != "#FFffff") {
let color2 = new THREE.Color(mapData.parkArea[i].childArea[m].color);
for (let e = 0; e < Map_QM.util.parkMaterialArr.length; e++) {
if (Map_QM.util.parkMaterialArr[e].color.equals(color2)) {
meshMaterial0 = Map_QM.util.parkMaterialArr[e];
}
}
if (!meshMaterial0) {
meshMaterial0 = new THREE.MeshBasicMaterial({
color: mapData.parkArea[i].childArea[m].color
});
Map_QM.util.parkMaterialArr.push(meshMaterial0);
}
} else {
meshMaterial0 = meshMaterial;
}
let ps = mapData.parkArea[i].childArea[m].points;
let shape0 = new THREE.Shape();
// 设置开始点的位置
shape0.moveTo(ps[0].x, -1 * ps[0].y);
for (let t = 0; t < ps.length; t++) {
shape0.lineTo(ps[t].x, -1 * ps[t].y);
}
shapeArr.push(shape0);
materials.push(meshMaterial0);
}
}
}
//显示车位编号
if (mapData.parkArea[i].parkNum != "NaN" && i % 10 == 0) {
let shopDiv = document.createElement('div');
shopDiv.style.cssText = css_LR
shopDiv.style.display = "none";
shopDiv.textContent = mapData.parkArea[i].parkNum;
let shopLabel = new THREE.CSS2DObject(shopDiv);
shopLabel.userData.mapShow = true; //是否永久显示
shopLabel.name = mapData.parkArea[i].name;
shopLabel.position.set(mapData.parkArea[i].xaxis >> 0, -1 * mapData.parkArea[i].yaxis >> 0, parseInt(mapData.parkArea[i].toHeight) + 1);
this.labelObj.add(shopLabel);
}
}
}
let mahc = this.Model_QM.MyParkShape(shapeArr, materials, parkHeight);
this.parkObj.add(mahc);
}
}
}
/**
* 渲染3D模型类
* 传入区域点list
* 镂空点 howllowArr
* 模型对象 options
*/
MyModel_QM = function () {
this.xaxis = 0
this.yaxis = 0
this.node = 0
}
MyModel_QM.prototype.MyParkShape = function (shapes, materials, toHeight = 5) {
let scanGeometry = new THREE.ShapeBufferGeometry(shapes, 1);
let material = new THREE.LineBasicMaterial({
color: "#aeaeae"
}); //材质对象lineColor
Map_QM.util.lineBasicMaterialArr.push(material);
// 创建模型
let mesh = new THREE.Mesh(scanGeometry, materials);
mesh.position.z = toHeight;
mesh.renderOrder = 300;
mesh.userData.type = "park";
let cubeEdges = new THREE.EdgesGeometry(scanGeometry, 60);
let cubeLine = new THREE.LineSegments(cubeEdges, material);
mesh.add(cubeLine);
return mesh;
}
MyModel_QM.prototype.MyModelShape = function (areaArr, howllowArr, opObj, entityColor = 0xdadada, lineColor = 0xeeeeee, indexOrder = 1) {
let len = areaArr.length;
if (len == 0) {
return;
}
let alphaModle = opObj.alphaModle / 100 || 0;
// 实例化shape对象
let shape = new THREE.Shape();
// 设置开始点的位置
shape.moveTo(areaArr[0][0], -1 * areaArr[0][1]);
for (let i = 0; i < areaArr.length; i++) {
if (areaArr[i].length == 4) {
shape.lineTo(areaArr[i][2], -1 * areaArr[i][3]);
} else {
shape.bezierCurveTo(areaArr[i][2], -1 * areaArr[i][3], areaArr[i][4], -1 * areaArr[i][5], areaArr[i][6], -1 * areaArr[i][7]);
}
}
let material;
let matcolor = new THREE.Color(lineColor)
for (let k = 0; k < Map_QM.util.lineBasicMaterialArr.length; k++) {
if (Map_QM.util.lineBasicMaterialArr[k].color.equals(matcolor)) {
material = Map_QM.util.lineBasicMaterialArr[k];
}
}
if (!material) {
material = new THREE.LineBasicMaterial({
color: lineColor,
opacity: 0.8,
transparent: true
}); //材质对象lineColor
Map_QM.util.lineBasicMaterialArr.push(material);
}
if (howllowArr && howllowArr.length > 0) {
for (let n = 0; n < howllowArr.length; n++) {
let hole = new THREE.Path(); // 添加孔洞
hole.moveTo(howllowArr[n][0][0], -1 * howllowArr[n][0][1]);
for (let k = 0; k < howllowArr[n].length; k++) {
if (howllowArr[n][k].length == 4) {
hole.lineTo(howllowArr[n][k][2], -1 * howllowArr[n][k][3]);
} else {
hole.bezierCurveTo(howllowArr[n][k][2], -1 * howllowArr[n][k][3], howllowArr[n][k][4], -1 * howllowArr[n][k][5], howllowArr[n][k][6], -1 * howllowArr[n][k][7]);
}
}
shape.holes.push(hole);
}
}
let scanGeometry, meshMaterial, options = {
depth: parseInt(opObj.toHeight),
bevelEnabled: false,
curveSegments: 12,
bevelThickness: 0,
bevelSize: 0,
bevelSegments: 0,
material: 0, //frontMaterial = green
extrudeMaterial: 1, //sideMaterial = gray
};
scanGeometry = new THREE.ExtrudeGeometry(shape, options);
let meshColor = new THREE.Color(entityColor);
for (let e = 0; e < Map_QM.util.meshMaterialArr.length; e++) {
if (Map_QM.util.meshMaterialArr[e].color && Map_QM.util.meshMaterialArr[e].color.equals(meshColor) && Map_QM.util.meshMaterialArr[e].opacity == alphaModle && !Map_QM.util.meshMaterialArr[e].userData.map) {
meshMaterial = Map_QM.util.meshMaterialArr[e];
}
}
if (!meshMaterial) {
meshMaterial = new THREE.MeshPhongMaterial({ //MeshStandardMaterial MeshPhongMaterial MeshBasicMaterial
color: entityColor,
transparent: true,
opacity: alphaModle,
side: THREE.DoubleSide,
depthTest: true
});
Map_QM.util.meshMaterialArr.push(meshMaterial);
}
if (opObj.angleY || opObj.angleZ) {
Map_QM.util.rotateYZ(scanGeometry, opObj.angleY * Math.PI / 180, opObj.angleZ * Math.PI / 180);
}
// 创建模型
let mesh;
if(opObj.map == "home"){
Map_QM.util.assignUVs(scanGeometry);
let mapMaterial,ceMaterial;
for (let e = 0; e < Map_QM.util.meshMaterialArr.length; e++) {
if (Map_QM.util.meshMaterialArr[e].userData.map == "front" && Map_QM.util.meshMaterialArr[e].opacity == alphaModle) {
mapMaterial = Map_QM.util.meshMaterialArr[e];
}
if (Map_QM.util.meshMaterialArr[e].userData.map == "c50" && Map_QM.util.meshMaterialArr[e].opacity == alphaModle) {
ceMaterial = Map_QM.util.meshMaterialArr[e];
}
}
if(!mapMaterial){
let texture = new THREE.TextureLoader().load(Map_QM.util.beforPath + "static/img/map/front.png");
texture.wrapS = THREE.ClampToEdgeWrapping;
texture.wrapT = THREE.RepeatWrapping;
mapMaterial = new THREE.MeshPhongMaterial({
color: entityColor,
map: texture,
transparent: true,
opacity: alphaModle,
side: THREE.DoubleSide,
depthTest: true
});
mapMaterial.userData.map = "front";
Map_QM.util.meshMaterialArr.push(mapMaterial);
}
if(!ceMaterial){
let texture2 = new THREE.TextureLoader().load(Map_QM.util.beforPath + "static/img/map/c50.png");
texture2.wrapS = THREE.RepeatWrapping;
texture2.wrapT = THREE.ClampToEdgeWrapping;
ceMaterial = new THREE.MeshPhongMaterial({
color: entityColor,
map: texture2,
transparent: true,
opacity: alphaModle,
side: THREE.DoubleSide,
depthTest: true
});
ceMaterial.userData.map = "c50";
Map_QM.util.meshMaterialArr.push(ceMaterial);
}
mesh = new THREE.Mesh(scanGeometry, [meshMaterial,ceMaterial,mapMaterial]);
} else if(opObj.map){
Map_QM.util.packUv(scanGeometry);
let ceMaterial;
for (let e = 0; e < Map_QM.util.meshMaterialArr.length; e++) {
if (Map_QM.util.meshMaterialArr[e].userData.map == opObj.map && Map_QM.util.meshMaterialArr[e].opacity == alphaModle) {
ceMaterial = Map_QM.util.meshMaterialArr[e];
}
}
if(!ceMaterial){
let texture2 = new THREE.TextureLoader().load(Map_QM.util.beforPath + "static/img/map/"+opObj.map+".png");
texture2.wrapS = THREE.RepeatWrapping;
texture2.wrapT = THREE.ClampToEdgeWrapping;
ceMaterial = new THREE.MeshPhongMaterial({
color: entityColor,
map: texture2,
transparent: true,
opacity: alphaModle,
side: THREE.DoubleSide,
depthTest: true
});
ceMaterial.userData.map = opObj.map;
Map_QM.util.meshMaterialArr.push(ceMaterial);
}
mesh = new THREE.Mesh(scanGeometry, [meshMaterial,ceMaterial]);
}else{
mesh = new THREE.Mesh(scanGeometry, meshMaterial);
}
if (opObj.type != "wall") {
let cubeEdges = new THREE.EdgesGeometry(scanGeometry, 60);
let cubeLine = new THREE.LineSegments(cubeEdges, material);
cubeLine.renderOrder = indexOrder - 5;
mesh.add(cubeLine);
}
if (opObj.name != "floor") {
mesh.position.z = opObj.site || 0;
} else {
mesh.position.z = -1 * parseInt(opObj.toHeight) - 1;
}
mesh.castShadow = true;
mesh.renderOrder = indexOrder;
mesh.name = opObj.name || "";
return mesh;
}
//绘制平面
MyModel_QM.prototype.MyPlaneShape = function (areaArr, howllowArr, opObj, entityColor = "#dadada", lineColor = "#eeeeee", indexOrder = 1) {
let len = areaArr.length;
if (len == 0) {
return;
}
let alphaModle = opObj.alphaModle / 100 || 0;
// 实例化shape对象
let shape = new THREE.Shape();
// 设置开始点的位置
shape.moveTo(areaArr[0][0], -1 * areaArr[0][1]);
for (let i = 0; i < areaArr.length; i++) {
if (areaArr[i].length == 4) {
shape.lineTo(areaArr[i][2], -1 * areaArr[i][3]);
} else {
shape.bezierCurveTo(areaArr[i][2], -1 * areaArr[i][3], areaArr[i][4], -1 * areaArr[i][5], areaArr[i][6], -1 * areaArr[i][7]);
}
}
let material;
for (let k = 0; k < Map_QM.util.lineBasicMaterialArr.length; k++) {
let color2 = new THREE.Color(lineColor)
if (Map_QM.util.lineBasicMaterialArr[k].color.equals(color2)) {
material = Map_QM.util.lineBasicMaterialArr[k];
}
}
if (!material) {
material = new THREE.LineBasicMaterial({
color: lineColor,
opacity: 0.8,
transparent: true
}); //材质对象lineColor
Map_QM.util.lineBasicMaterialArr.push(material);
}
if (howllowArr && howllowArr.length > 0) {
for (let n = 0; n < howllowArr.length; n++) {
let hole = new THREE.Path(); // 添加孔洞
hole.moveTo(howllowArr[n][0][0], -1 * howllowArr[n][0][1]);
for (let k = 0; k < howllowArr[n].length; k++) {
if (howllowArr[n][k].length == 4) {
hole.lineTo(howllowArr[n][k][2], -1 * howllowArr[n][k][3]);
} else {
hole.bezierCurveTo(howllowArr[n][k][2], -1 * howllowArr[n][k][3], howllowArr[n][k][4], -1 * howllowArr[n][k][5], howllowArr[n][k][6], -1 * howllowArr[n][k][7]);
}
}
shape.holes.push(hole);
}
}
let scanGeometry, meshMaterial;
scanGeometry = new THREE.ShapeGeometry(shape, 8);
Map_QM.util.assignUVs(scanGeometry);
if(opObj.map){
let texture = new THREE.TextureLoader().load(Map_QM.util.beforPath + "static/img/map/" + opObj.map + ".png");
meshMaterial = new THREE.MeshPhongMaterial({ //MeshStandardMaterial MeshPhongMaterial olor: entityColor,
color: entityColor,
map: texture,
transparent: true,
opacity: alphaModle,
side: THREE.DoubleSide,
depthTest: true
});
meshMaterial.userData.map = opObj.map;
Map_QM.util.meshMaterialArr.push(meshMaterial);
}else{
for (let e = 0; e < Map_QM.util.meshMaterialArr.length; e++) {
let color2 = new THREE.Color(entityColor);
if (Map_QM.util.meshMaterialArr[e].color && Map_QM.util.meshMaterialArr[e].color.equals(color2) && Map_QM.util.meshMaterialArr[e].opacity == alphaModle && !Map_QM.util.meshMaterialArr[e].userData.map) {
meshMaterial = Map_QM.util.meshMaterialArr[e];
}
}
if (!meshMaterial) {
meshMaterial = new THREE.MeshPhongMaterial({
color: entityColor,
transparent: true,
opacity: alphaModle,
side: THREE.DoubleSide,
depthTest: true
});
Map_QM.util.meshMaterialArr.push(meshMaterial);
}
if (opObj.angleY || opObj.angleZ) {
Map_QM.util.rotateYZ(scanGeometry, opObj.angleY * Math.PI / 180, opObj.angleZ * Math.PI / 180);
}
}
// 创建模型
let mesh = new THREE.Mesh(scanGeometry, meshMaterial);
let cubeEdges = new THREE.EdgesGeometry(scanGeometry, 60);
let cubeLine = new THREE.LineSegments(cubeEdges, material);
cubeLine.renderOrder = indexOrder - 5;
mesh.add(cubeLine);
if (opObj.name != "floor") {
mesh.position.z = parseInt(opObj.toHeight) || 0;
}
mesh.castShadow = true;
mesh.renderOrder = indexOrder;
mesh.name = opObj.name || "";
return mesh;
}
MyModel_QM.prototype.MyModelText = function (svgArea) {
let text = svgArea.data;
const paths = new THREE.SVGLoader().parse(text).paths;
const group = new THREE.Group();
group.position.x = parseInt(svgArea.xaxis);
group.position.y = -1 * parseInt(svgArea.yaxis);
group.position.z = parseInt(svgArea.site || 0);
group.rotateX(parseInt(svgArea.angleZ) * Math.PI / 180);
group.rotateY(parseInt(svgArea.angleY) * Math.PI / 180);
group.rotateZ(parseInt(svgArea.angle) * Math.PI / 180);
group.scale.multiplyScalar(svgArea.scale);
group.scale.y *= -1;
let meshMaterial;
for (let e = 0; e < Map_QM.util.meshMaterialArr.length; e++) {
let color2 = new THREE.Color().setHex(svgArea.entColor);
if (Map_QM.util.meshMaterialArr[e].color && Map_QM.util.meshMaterialArr[e].color.equals(color2) && Map_QM.util.meshMaterialArr[e].opacity == svgArea.alphaModle) {
meshMaterial = Map_QM.util.meshMaterialArr[e];
}
}
if (!meshMaterial) {
meshMaterial = new THREE.MeshStandardMaterial({
color: svgArea.entColor,
opacity: parseInt(svgArea.alphaModle) / 100
});
Map_QM.util.meshMaterialArr.push(meshMaterial);
}
for (let i = 0; i < paths.length; i++) {
const path = paths[i];
let shapes = path.toShapes(true);
const geometry = new THREE.ShapeGeometry(shapes, 12);
const mesh = new THREE.Mesh(geometry, meshMaterial);
mesh.renderOrder = 50;
mesh.name = svgArea.name || "";
mesh.position.set(svgArea.width / -2, svgArea.height / -2, parseInt(svgArea.toHeight)+1);
group.add(mesh);
}
return group;
}
/**
* 公共设施
*/
MySprite_QM = function (spriteMaterial, obj = null) {
THREE.Sprite.call(this)
if (obj) {
this.navCode = obj.navCode
this.no = obj.no
this.facCode = obj.facCode
this.floor = obj.floorOrder
this.build = obj.buildOrder
this.site = parseInt(obj.site) || Map_QM.util.shopHeight + 32
}
this.imgUrl
this.material = spriteMaterial !== undefined ? spriteMaterial : new SpriteMaterial()
//图标跳动
this.jumpIcon = function () {
let oldZ = this.site
let self = this
TweenMax.fromTo(
self.position,
0.5,
{ z: oldZ },
{
z: oldZ + 20,
repeat: 1,
onComplete: function () {
TweenMax.to(self.position, 0.2, { z: oldZ })
}
}
)
}
this.reSetSite = function () {
//重置位置
this.position.z = this.site
}
}
MySprite_QM.prototype = Object.create(THREE.Sprite.prototype)
MySprite_QM.prototype.constructor = MySprite_QM
/**
* 渲染公共设施
*/
Facilities_QM = function () {
this.renderIcon = function (obj, _this, isShow = true, ele = null) {
if (obj) {
let url = Map_QM.util.beforPath + "static/img/" + obj.facCode + ".png";
let name = obj.title;
let nameEn = obj.title;
if (Map_QM.util.iconUrl.length > 0) { //使用设施库
for (let i = 0; i < Map_QM.util.iconUrl.length; i++) {
if (Map_QM.util.iconUrl[i].abbreviation == obj.facCode) {
url = Map_QM.util.iconUrl[i].navFilePath
name = Map_QM.util.iconUrl[i].name;
nameEn = Map_QM.util.iconUrl[i].nameEn;
}
}
}
let shopDiv = document.createElement('img');
shopDiv.src = url;
shopDiv.style.zIndex = 200;
shopDiv.style.width = "1.2vw";
shopDiv.style.display = isShow?"":"none";
let shopLabel = new THREE.CSS2DObject(shopDiv);
shopLabel.userData.mapShow = true; //是否永久显示
shopLabel.userData = obj;
shopLabel.userData.type = "icon";
shopLabel.userData.use = ele ? "2d" : "all";
shopLabel.userData.model = ele;
shopLabel.userData.src = url;
shopLabel.userData.isShow = true;
shopLabel.position.set(obj.x, -1 * obj.y, Math.max(30, parseInt(obj.site) || 0));
_this.serObj.add(shopLabel);
if (Map_QM.util.options.iconName) {
let shopDiv = document.createElement('div');
shopDiv.style.cssText = css_LR
if(window.innerWidth>2000){
shopDiv.style.height = "20px";
shopDiv.style.fontSize = "18px";
}
shopDiv.innerText = obj.title;
shopDiv.dataset.name = name;
shopDiv.dataset.nameEn = nameEn;
let shopLabel = new THREE.CSS2DObject(shopDiv);
shopLabel.position.set(obj.x, -1 * obj.y, 30);
shopLabel.userData.mapShow = true;
_this.labelObj.add(shopLabel);
}
}
}
}
/**
* 店铺LOGO地图展示类
*/
ShopLogo_QM = function () {
this.renderIcon = function (obj, _this, z) {
if (obj) {
let x = obj.xaxis >> 0
let y = (-1 * obj.yaxis) >> 0
let imgW = obj.imgW >> 0
let imgH = obj.imgH >> 0
new THREE.TextureLoader().load(obj.logoUrl, textu => {
let planeMaterial = new THREE.MeshPhongMaterial({
map: textu,
depthTest: true,
transparent: true,
alphaTest:0.01
})
let planeGeometry = new THREE.PlaneGeometry(imgW, imgH)
let plane = new THREE.Mesh(planeGeometry, planeMaterial)
plane.center = new THREE.Vector2(0, 0)
plane.position.set(x, y, obj.site || z)
plane.userData.rot = 0
plane.userData.type = 'logo'
plane.renderOrder = 70
_this.add(plane)
})
}
}
}
var _selfFindPath
FindPath_QM = function () {
this.pathArr = []
this.lineDashed_old
//路线指引箭头皮肤
this.planeGeometry = new THREE.PlaneGeometry(128, 128)
this.stop = null
this._index = 0 //寻路用
this.pathState = 'init'
this.pathPlay = {
_isPlay: false,
get isPlay() {
return this._isPlay
},
set isPlay(val) {
this._isPlay = val
if (_selfFindPath && _selfFindPath.stop) {
window.cancelAnimationFrame(_selfFindPath.stop)
_selfFindPath.stop = null
}
if (_selfFindPath && _selfFindPath.pathState == 'isPlay' && _selfFindPath._index < _selfFindPath.pathArr.length) {
_selfFindPath.playMoveGuide()
}
}
}
}
FindPath_QM.prototype.clearPath = function () {
this.pathArr = []
if (this.lineDashed_old) {
if (Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor]) {
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.remove(this.lineDashed_old)
}
this.lineDashed_old.destroy()
this.lineDashed_old = null
}
if (Map_QM.guide) {
Map_QM.guide.visible = false
if (Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor]) {
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.remove(Map_QM.man_2d)
Map_QM.mapArr[Map_QM.util.selectBuild][Map_QM.util.selectFloor].allObj.remove(Map_QM.man_3d)
}
}
if (_selfFindPath && _selfFindPath.stop) {
window.cancelAnimationFrame(_selfFindPath.stop)
}
this._index = 0
this.pathState = 'init'
}
/**
* @param {Object} startNade
* @param {Object} toNade
* @param {Object} callBack 回调函数
*/
FindPath_QM.prototype.onFindPathAnimation = function (pathArray, floorOrder = -1) {
if (pathArray && pathArray.length > 0) {
this.pathArr = []
for (let j = 0; j < pathArray.length; j++) {
this.pathArr.push(pathArray[j])
}
this.pathState = 'isPlay'
this._index = 0
if (floorOrder === -1) {
floorOrder = Map_QM.util.selectFloor
}
this.drawPath(floorOrder)
}
}
FindPath_QM.prototype.drawPath = function (floorOrder) {
let linePath = []
for (let i = 0; i < this.pathArr.length; i++) {
if (i < this.pathArr.length) {
linePath.push([this.pathArr[i].x, -1 * this.pathArr[i].y])
}
}
this.lineDashed_old = new PathLine(12, linePath, parseInt(Map_QM.util.buildHeight) + 1, Map_QM.util.options.pathColor, Map_QM.util.options.pathColor2, true)
this.lineDashed_old.name = 'lineDash'
this.lineDashed_old.renderOrder = 128
Map_QM.mapArr[Map_QM.util.selectBuild][floorOrder].allObj.add(this.lineDashed_old)
////////////////////////////////////////////////////////
}
FindPath_QM.prototype.guidePathPlay = function (paths) {
if (Map_QM.guide) {
Map_QM.guide.renderOrder = 99
if (paths.PathPoint) {
Map_QM.guide.position.x = paths.PathPoint[0].x
Map_QM.guide.position.y = -1 * paths.PathPoint[0].y
Map_QM.moveCameraBy2D(paths.PathPoint[0])
Map_QM.man_2d.position.z = parseInt(Map_QM.util.buildHeight) + 120
Map_QM.man_3d.position.z = parseInt(Map_QM.util.buildHeight) + 5
Map_QM.guide.visible = true
Map_QM.mapArr[Map_QM.util.selectBuild][paths.floor].allObj.add(Map_QM.man_2d)
Map_QM.mapArr[Map_QM.util.selectBuild][paths.floor].allObj.add(Map_QM.man_3d)
}
}
this.pathArr = paths.PathPoint
_selfFindPath = this
if (Map_QM.util.pathStateObj.isPathPlay) {
this.pathPlay.isPlay = true
}
}
/**
* 播放图标指引动画
*/
FindPath_QM.prototype.playMoveGuide = function () {
if (!Map_QM.guide) {
return
}
let px = Map_QM.guide.position.x
let py = Map_QM.guide.position.y
let targetX = _selfFindPath.pathArr[_selfFindPath._index].x - px
let targetY = -1 * _selfFindPath.pathArr[_selfFindPath._index].y - py
let dist = Math.sqrt(targetX * targetX + targetY * targetY)
let df = Math.ceil(dist / Map_QM.util.options.playSpeed)
let dx = (_selfFindPath.pathArr[_selfFindPath._index].x - px) / df
let dy = (-1 * _selfFindPath.pathArr[_selfFindPath._index].y - py) / df
let ang = 0
if (df < 2) {
Map_QM.guide.position.x = _selfFindPath.pathArr[_selfFindPath._index].x
Map_QM.guide.position.y = -1 * _selfFindPath.pathArr[_selfFindPath._index].y
Map_QM.moveCameraBy2D({ x: _selfFindPath.pathArr[_selfFindPath._index].x, y: _selfFindPath.pathArr[_selfFindPath._index].y })
_selfFindPath._index++
if (_selfFindPath._index > 0 && _selfFindPath._index < _selfFindPath.pathArr.length) {
Map_QM.man_3d.rotation.z = Map_QM.man_2d.rotation.z = 0 //180;
let s = Math.sqrt(
(_selfFindPath.pathArr[_selfFindPath._index].x - _selfFindPath.pathArr[_selfFindPath._index - 1].x) *
(_selfFindPath.pathArr[_selfFindPath._index].x - _selfFindPath.pathArr[_selfFindPath._index - 1].x) +
(_selfFindPath.pathArr[_selfFindPath._index].y - _selfFindPath.pathArr[_selfFindPath._index - 1].y) *
(_selfFindPath.pathArr[_selfFindPath._index].y - _selfFindPath.pathArr[_selfFindPath._index - 1].y)
)
ang = Math.acos((_selfFindPath.pathArr[_selfFindPath._index].y - _selfFindPath.pathArr[_selfFindPath._index - 1].y) / s)
if (_selfFindPath.pathArr[_selfFindPath._index].x < _selfFindPath.pathArr[_selfFindPath._index - 1].x) {
Map_QM.man_3d.rotation.z = Map_QM.man_2d.rotation.z = Math.PI - ang
} else {
Map_QM.man_3d.rotation.z = Map_QM.man_2d.rotation.z = Math.PI + ang
}
}
let pathShop = ''
for (let t = 0; t < Map_QM.forShopArr[Map_QM.util._indexPathFloor].wayShop.length; t++) {
if (Map_QM.forShopArr[Map_QM.util._indexPathFloor].wayShop[t].pathIndex == _selfFindPath._index) {
let shop_ = Map_QM.forShopArr[Map_QM.util._indexPathFloor].wayShop[t].shop
pathShop = shop_.houseNumber
let shops = Map_QM.mapArr[Map_QM.util.selectBuild][parseInt(Map_QM.forShopArr[Map_QM.util._indexPathFloor].wayShop[t].shop.floorOrder)].allObj.children
for (let i = 0; i < shops.length; i++) {
let _shop = shops[i].userData.shopData
if (_shop && _shop.houseNumber === pathShop) {
let shopModel = shops[i]
let material = shopModel.material
shopModel.material = new THREE.MeshBasicMaterial({ color: Map_QM.util.options.navColor })
TweenMax.to(shopModel.scale, 0.8, {
z: 3,
yoyo: true,
ease: Cubic.easeIn,
onComplete: function () {
if (shopModel) {
TweenMax.to(shopModel.scale, 0.5, { z: 1 })
shopModel.material = material
}
}
})
break
}
}
break
}
}
Map_QM.dispatchEvent({
//寻路中返回小人当前所在点位
type: 'PathPlaying',
data: { shopNum: pathShop }
})
} else {
px += dx
py += dy
Map_QM.guide.position.x = px
Map_QM.guide.position.y = py
Map_QM.moveCameraBy2D({ x: px, y: -1 * py })
}
if (_selfFindPath.pathPlay.isPlay && Map_QM.guide) {
if (_selfFindPath._index < _selfFindPath.pathArr.length) {
_selfFindPath.stop = requestAnimationFrame(_selfFindPath.playMoveGuide)
} else {
if (_selfFindPath && _selfFindPath.stop) {
window.cancelAnimationFrame(_selfFindPath.stop)
_selfFindPath.stop = null
}
_selfFindPath._index = 0
if (Map_QM.guide) {
Map_QM.guide.visible = false
}
let myEvent = new CustomEvent('pathOver', {
detail: { dx: dx, dy: dy }
})
document.dispatchEvent(myEvent) //触发导航完成事件
_selfFindPath.pathState = 'pathOver'
}
}
}