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.
5852 lines
206 KiB
5852 lines
206 KiB
var Map_QM,
|
|
elevator,
|
|
straight,
|
|
elevatorDown,
|
|
deviceJSON,
|
|
renderFrame = -1,
|
|
timeS = 0,
|
|
_indexPathFloor = 0,
|
|
pathShop = '',
|
|
clock = new THREE.Clock()
|
|
var outTime = -1,
|
|
oTime = -1,
|
|
language = 'cn',
|
|
deviceShow = false,
|
|
iconNameShow = false,
|
|
forShopArr = {} //deviceShow 设备图标是否显示 iconNameShow--图标名称是否显示
|
|
var isPathPlay = true,
|
|
basePath = '',
|
|
graphPath = '',
|
|
ftPath = '',
|
|
dtPath = '',
|
|
facAllArr = [] //basePath 基础路径 graphPath最佳路径 ftPath 扶梯路径 dtPath 电梯路径
|
|
var cameraPerspective,
|
|
cameraOrtho,
|
|
aspect,
|
|
isPathState = false,
|
|
pathCameraState = '2D' //
|
|
|
|
ConfigFun = function () {
|
|
this.imgUrl = 'http://1000my.com/MallSite'
|
|
this.playSpeed = 6 //动画播放速度
|
|
this.collision = true //是否支持名称的碰撞检测
|
|
this.selectBuild = 0
|
|
this.selectFloor = 0
|
|
this.is4k = false //是否4K显示
|
|
this.showModelIcon = true //电梯扶梯是否显示3D模型 true 模型 false 图标
|
|
this.deviceObj = {} //angle --- 设备旋转角度 node ---- 设备导航点位 floor --- 设备楼层
|
|
this.startObj = {} // 导航起点;
|
|
this.overObj = {} //导航结束点
|
|
this.otherPath = null //人为干预的路线
|
|
this.distance = 6000 //楼栋间距
|
|
this.mapDistance = { min: 100, max: 1000 } //限制地图缩放
|
|
this.tubeMaterial = new THREE.MeshPhongMaterial({ color: 0xb47834, transparent: true, opacity: 0.6 }) //路径材质
|
|
this.cameraDist = { x: 0, y: 220, z: 220, state: '3D' } //相机坐标 state---2D 平面 3D 立体
|
|
this.sceneGap = { x: 0, y: 0, z: 0, scale: 0.095 } //改变地图位置,大小
|
|
this.cameraZoom = 3 //设置我的方向状态地图放大倍数;
|
|
this.deviceAng = false //地图初始化方向是否使用设备角度
|
|
this.showlap = false //showlap 是否叠层预览
|
|
this.mapAngle = 0 //如果不使用设备角度则此值可设置默认角度;
|
|
this.perc_H = '-50%' //弹窗的偏移百分比17 或者像素
|
|
this.doubleDist = 500 //双叠层状态下楼层的间距
|
|
this.overlap = false //是否叠层
|
|
this.mapScale = 6 //地图比例尺
|
|
this.angleRadius = 2 //圆角半径 大于2 则店铺box显示圆角
|
|
this.buildHeight = 5
|
|
this.shopHeight = 50 //店铺高度
|
|
this.parkMaterial = new THREE.MeshBasicMaterial({
|
|
//MeshBasicMaterial MeshLambertMaterial MeshPhongMaterial
|
|
color: 0xffffff
|
|
}) //isPathState--导航状态
|
|
this.navColor = 0xee6a50
|
|
//服务icon 英文配置
|
|
this.iconEn = { 洗手间: 'Toilets', 停车场: 'Parking', 电梯: 'Lift', 扶梯: 'Escalator', 母婴室: 'Baby care room', 服务台: 'service desk' }
|
|
this.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}}
|
|
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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ key: 'penquan1', url: 'static/img/model/penquan1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ key: 'zuoyi1', url: 'static/img/model/zuoyi1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 } },
|
|
{ key: 'zuoyi2', url: 'static/img/model/zuoyi2.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 } },
|
|
{ key: 'zhuozi1', url: 'static/img/model/zhuozi1.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 30, y: 20, z: 30 } },
|
|
{ key: 'zhuozi2', url: 'static/img/model/zhuozi2.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 30, y: 20, z: 30 } },
|
|
{ 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 } },
|
|
{ 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 } },
|
|
{ key: 'ggp', url: 'static/img/model/ggp.glb', colorModel: 'gama', rot: { x: 1.5708, y: 0, z: 0 }, size: { x: 20, y: 20, z: 20 } }
|
|
]
|
|
this.fbxModels = [] //精灵模型
|
|
//标签数据 click --是否可点击
|
|
this.labelIconArr = []
|
|
this.spriteMaterialArr = []
|
|
this.lineBasicMaterialArr = []
|
|
this.meshMaterialArr = []
|
|
this.shopData = [] //店铺数据
|
|
this.allMap = []
|
|
/*** ------------------------------------------------ 参数 API START ------------------------------------------------- */
|
|
/**
|
|
* @api {方法} setModelState() 模型显示状态
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 设置模型显示状态 默认 3d
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {String} state 传入状态 2d 或 3d
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setModelState("3d");
|
|
*/
|
|
this.setModelState = function (state = '3d') {
|
|
//设置模型显示状态 2d 3d
|
|
if (Map_QM) {
|
|
Map_QM.renderer.clear()
|
|
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 {方法} setIconNameShow() 设施名称显隐
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 设置设施名称显示或隐藏
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {boolean} isShow 是否显示 true显示 false隐藏
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {boolean} 请求示例
|
|
*
|
|
* Config.setIconNameShow(true);
|
|
*/
|
|
this.setIconNameShow = function (isShow) {
|
|
iconNameShow = isShow
|
|
}
|
|
/**
|
|
* @api {方法} setPlaySpeed() 改变导航速度
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 改变导航播放速度,范围 2-20 默认是6
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} speed 播放速度
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setPlaySpeed(8);
|
|
*/
|
|
this.setPlaySpeed = function (sp) {
|
|
this.playSpeed = parseInt(sp)
|
|
}
|
|
//设置弹窗偏离位置 默认 -50% 范围 -100% 100%
|
|
this.setPercH = function (perc = '-50%') {
|
|
this.perc_H = perc
|
|
}
|
|
/**
|
|
* @api {方法} setDeviceShow() 设备显示状态
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 设置设备的显示状态 默认false
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {boolean} value 是否显示
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {boolean} 请求示例
|
|
*
|
|
* Config.setDeviceShow(true);
|
|
*/
|
|
this.setDeviceShow = function (value) {
|
|
deviceShow = value
|
|
}
|
|
//
|
|
/**
|
|
* @api {方法} setCollision() 设置碰撞检测
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 设置box名称是否支持碰撞检测 默认支持
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {boolean} value 是否支持
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setCollision(true);
|
|
*/
|
|
this.setCollision = function (value) {
|
|
this.collision = value
|
|
}
|
|
/**
|
|
* @api {方法} setShowModelIcon() 公共设施模型
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 设置公共设施模型效果 true 3D模型 false icon显示
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {boolean} value 显示状态
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setShowModelIcon(true);
|
|
*/
|
|
this.setShowModelIcon = function (value) {
|
|
this.showModelIcon = value
|
|
}
|
|
/**
|
|
* @api {方法} setSceneGap() 地图模型展示
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 设置公共设施模型效果 x/y/z 模型中心点位置
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {Number} x 水平方向位置,负数左移,正数右移
|
|
* @apiParam {Number} y 垂直方向位置,负数下移,正数上移
|
|
* @apiParam {Number} z 远近位置,默认为0
|
|
* @apiParam {Number} scale 缩放默认为0.1
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setSceneGap({x:0,y:0,z:0,scale:0.1});
|
|
*/
|
|
this.setSceneGap = function (value) {
|
|
this.sceneGap = value
|
|
}
|
|
|
|
//设置其它可行路径
|
|
this.setOtherPath = function (value) {
|
|
this.otherPath = value
|
|
}
|
|
/**
|
|
* 是否所有楼层叠层显示
|
|
* @param {boolean} value
|
|
*/
|
|
this.setShowLap = function (value) {
|
|
Config.showlap = value
|
|
Map_QM.showFloor(Config.deviceObj.floor)
|
|
}
|
|
|
|
/**
|
|
* @api {方法} setSceneGapInit() 地图初始参数
|
|
* @apiGroup 地图数据
|
|
* @apiDescription 设置地图初始位置、大小
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} x X轴上位移
|
|
* @apiParam {int} y Y轴上位移
|
|
* @apiParam {int} z Z轴上位移
|
|
* @apiParam {Number} scale 地图缩放比例
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setSceneGapInit({x:-100,y:0,z:0,scale:0.1});
|
|
*/
|
|
this.setSceneGapInit = function (value) {
|
|
this.sceneGap = value
|
|
}
|
|
//
|
|
/**
|
|
* @api {方法} setLabelIconArr() 设置外部标签
|
|
* @apiGroup 地图数据
|
|
* @apiDescription 设置外部标签
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {Array} value 标签数组
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setLabelIconArr([{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.setLabelIconArr = function (value) {
|
|
this.labelIconArr = value
|
|
}
|
|
/**
|
|
* @api {方法} setModelArr() 设置外部模型
|
|
* @apiGroup 地图数据
|
|
* @apiDescription 设置外部模型
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {Array} value 模型数组
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.setModelArr({floor:0,url:'./static/img/model/yj.gltf',list:[{site:{x :0, y :0, z :0}, rot:{x :1.5708, y :0, z :0}, size:{x :1, y :1, z :1}} ]});
|
|
*/
|
|
this.setModelArr = function (value) {
|
|
this.modelArr = value
|
|
}
|
|
/**
|
|
* @api {方法} getInstance() 初始化方法
|
|
* @apiGroup 地图数据
|
|
* @apiDescription 地图数据初始化 (可重复调用)
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {Function} callBack 回调函数
|
|
* @apiParam {int} build 导航起点楼栋编号
|
|
* @apiParam {int} floor 导航起点楼层编号
|
|
* @apiParam {int} navPoint 导航起点点位编号 传 -1 不显示起点
|
|
* @apiParam {int} angle 导航起点初始角度
|
|
* @apiParam {String} mallCode 商场Code (可选)
|
|
* @apiParam {String} _url 云地址 (可选)
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Config.getInstance(,0,1,1,0,"993f60c6-fef5-4999-9c3e-a4f71eb48364","http://122.112.233.82/mall");
|
|
*
|
|
* @apiSuccess {int} code 状态码 200-正常;404-地图无法显示;500-地图关联数据错误
|
|
* @apiSuccess {String} msg 状态提示信息
|
|
* @apiSuccess {Array} data 返回楼层数据
|
|
* @apiSuccessExample {json} success-example
|
|
* {
|
|
* "code": 200,
|
|
* "msg": "加载成功"
|
|
* "data": []
|
|
* }
|
|
*/
|
|
this.getInstance = function (callBack, build = 0, floor = 0, navPoint = 1, angle = 0, mapData, shopData) {
|
|
Config.startObj.build = Config.deviceObj.build = parseInt(build) || 0
|
|
Config.startObj.floor = Config.deviceObj.floor = parseInt(floor) || 0
|
|
Config.startObj.node = Config.deviceObj.node = parseInt(navPoint) || 1
|
|
Config.deviceObj.angle = parseInt(angle) || 0
|
|
Config.selectFloor = Config.deviceObj.floor
|
|
Config.selectBuild = Config.deviceObj.build
|
|
|
|
let backObj = { code: 200, msg: '加载成功', data: [] }
|
|
if (mapData) {
|
|
try {
|
|
if (mapData.mallKey != 'Zeditor') {
|
|
Config.allMap = JSON.parse(mapData.mapData)
|
|
} else {
|
|
Config.allMap = JSON.parse(LZString.decompressFromBase64(mapData.mapData))
|
|
}
|
|
} catch (e) {
|
|
console.log(e)
|
|
backObj.code = 404
|
|
backObj.msg = '地图数据JSON格式错误'
|
|
callBack(backObj)
|
|
callBack = null
|
|
}
|
|
Config.getShopData(callBack, shopData)
|
|
}
|
|
}
|
|
/*** ----------------------------------------------- 参数 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.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.encrypt = function (word, keyStr) {
|
|
keyStr = keyStr ? keyStr : '0123456789QMSaas'
|
|
var key = CryptoJS.enc.Utf8.parse(keyStr) //Latin1 w8m31+Yy/Nw6thPsMpO5fg==
|
|
var srcs = CryptoJS.enc.Utf8.parse(word)
|
|
var encrypted = CryptoJS.AES.encrypt(srcs, key, {
|
|
mode: CryptoJS.mode.ECB,
|
|
padding: CryptoJS.pad.Pkcs7
|
|
})
|
|
return encrypted.toString()
|
|
}
|
|
//解密
|
|
this.decrypt = function (word, keyStr) {
|
|
keyStr = keyStr ? keyStr : '0123456789QMSaas'
|
|
var key = CryptoJS.enc.Utf8.parse(keyStr) //Latin1 w8m31+Yy/Nw6thPsMpO5fg==
|
|
var decrypt = CryptoJS.AES.decrypt(word, key, {
|
|
mode: CryptoJS.mode.ECB,
|
|
padding: CryptoJS.pad.Pkcs7
|
|
})
|
|
return CryptoJS.enc.Utf8.stringify(decrypt).toString()
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
//判断点是fou顺时针
|
|
this.isClockwise = function (polygon) {
|
|
let len = polygon.length
|
|
let su = 0,
|
|
ni = 0
|
|
for (let i = 0; i < len; i++) {
|
|
let p = polygon[i]
|
|
let p1 = polygon[i == 0 ? len - 1 : i - 1]
|
|
let p2 = polygon[i == len - 1 ? 0 : i + 1]
|
|
let vx1 = p1.x - p.x
|
|
let vy1 = p1.y - p.y
|
|
let vx2 = p2.x - p.x
|
|
let vy2 = p2.y - p.y
|
|
// 负值多是顺时针,正值多是逆时针
|
|
if (vx1 * vy2 + -1 * vy1 * vx2 < 0) {
|
|
su++
|
|
} else {
|
|
ni++
|
|
}
|
|
return su > ni
|
|
}
|
|
}
|
|
|
|
this.blocked = (dom, checkList, cfloor) => {
|
|
const { top, left, right, bottom } = dom.getBoundingClientRect()
|
|
let corners = [
|
|
[left, top],
|
|
[right, top],
|
|
[left, bottom],
|
|
[right, bottom]
|
|
]
|
|
|
|
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('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
|
|
}
|
|
//绘制3D线 传入起点(3D坐标)、终点(3D坐标)、控制点1、控制点2(如没有则绘制直线)
|
|
this.drawDashedLine = function (startPoint, endPoint, dash = 50, color = 0x2269dd, ctrlPoint1 = null, ctrlPoint2 = null) {
|
|
//THREE.Vector3
|
|
let gopObj = new THREE.Group()
|
|
let curve
|
|
if (!ctrlPoint1 && !ctrlPoint2) {
|
|
//控制点为空
|
|
ctrlPoint1 = new THREE.Vector3(
|
|
startPoint.x + (endPoint.x - startPoint.x) / 4,
|
|
startPoint.y + (endPoint.y - startPoint.y) / 4,
|
|
startPoint.z + (endPoint.z - startPoint.z) / 4
|
|
)
|
|
ctrlPoint2 = new THREE.Vector3(
|
|
endPoint.x + (startPoint.x - endPoint.x) / 4,
|
|
endPoint.y + (startPoint.y - endPoint.y) / 4,
|
|
endPoint.z + (startPoint.z - endPoint.z) / 4
|
|
)
|
|
}
|
|
curve = new THREE.CubicBezierCurve3(startPoint, ctrlPoint1, ctrlPoint2, endPoint)
|
|
let points = curve.getPoints(dash)
|
|
let array = []
|
|
points.forEach(element => {
|
|
array.push(element.x, element.y, element.z)
|
|
})
|
|
let geometry = new THREE.LineSegmentsGeometry()
|
|
// 几何体传入顶点坐标
|
|
geometry.setPositions(array)
|
|
// 自定义的材质
|
|
let material = new THREE.LineMaterial({
|
|
color: color,
|
|
linewidth: 4,
|
|
scale: 1,
|
|
dashSize: 1,
|
|
gapSize: 2
|
|
})
|
|
// 把渲染窗口尺寸分辨率传值给材质LineMaterial的resolution属性
|
|
// resolution属性值会在着色器代码中参与计算
|
|
material.resolution.set(window.innerWidth, window.innerHeight)
|
|
let mesh = new THREE.Mesh(geometry, material)
|
|
gopObj.add(mesh)
|
|
let jtArr = []
|
|
if (Math.abs(endPoint.x - startPoint.x) > Math.abs(endPoint.y - startPoint.y)) {
|
|
jtArr.push(endPoint.x - 10, endPoint.y, endPoint.z + 10)
|
|
jtArr.push(endPoint.x, endPoint.y, endPoint.z)
|
|
jtArr.push(endPoint.x + 10, endPoint.y, endPoint.z + 10)
|
|
jtArr.push(endPoint.x, endPoint.y, endPoint.z)
|
|
jtArr.push(endPoint.x, endPoint.y, endPoint.z + 10)
|
|
} else {
|
|
jtArr.push(endPoint.x, endPoint.y - 10, endPoint.z + 10)
|
|
jtArr.push(endPoint.x, endPoint.y, endPoint.z)
|
|
jtArr.push(endPoint.x, endPoint.y + 10, endPoint.z + 10)
|
|
jtArr.push(endPoint.x, endPoint.y, endPoint.z)
|
|
jtArr.push(endPoint.x, endPoint.y, endPoint.z + 10)
|
|
}
|
|
let jtgeom = new THREE.LineGeometry()
|
|
jtgeom.setPositions(jtArr)
|
|
let jtmesh = new THREE.Mesh(jtgeom, material)
|
|
gopObj.add(jtmesh)
|
|
gopObj.userData.type = 'toLine'
|
|
return gopObj
|
|
}
|
|
/**碰撞检测
|
|
* 传入A中心点和A的宽、高
|
|
* B的中心点和B的宽、高
|
|
*/
|
|
this.isCollision = function (A, aW, aH, B, bW, bH) {
|
|
let noCol = false
|
|
if (Math.abs(A.x - B.x) < (aW + bW) / 2 + 20 && Math.abs(A.y - B.y) < (aH + bH) / 2 + 10) {
|
|
noCol = true
|
|
}
|
|
return noCol
|
|
}
|
|
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 = Config.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 Config.Point(area.hasLines[m].startPoint.x, area.hasLines[m].startPoint.y)
|
|
ePoint = new Config.Point(area.hasLines[m].endPoint.x, area.hasLines[m].endPoint.y)
|
|
if (area.hasLines[m].isStrLine) {
|
|
cPoint1 = null
|
|
cPoint2 = null
|
|
} else {
|
|
cPoint1 = new Config.Point(area.hasLines[m].ctrlPoint1.x, area.hasLines[m].ctrlPoint1.y)
|
|
cPoint2 = new Config.Point(area.hasLines[m].ctrlPoint2.x, area.hasLines[m].ctrlPoint2.y)
|
|
}
|
|
let line = new Config.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 (Config.angleRadius > 2) {
|
|
if (
|
|
line0.isStrLine &&
|
|
line1.isStrLine &&
|
|
Math.abs(line0.endPoint.x - line0.startPoint.x) + Math.abs(line0.endPoint.y - line0.startPoint.y) > parseInt(Config.angleRadius) * 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 = Config.getIncircleByLines(x1, y1, x2, y2, x3, y3, Config.angleRadius)
|
|
let bezierResult = Config.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,
|
|
Config.angleRadius
|
|
)
|
|
|
|
if (i > 0) {
|
|
let ctrlPoint1,
|
|
ctrlPoint2,
|
|
array = []
|
|
ctrlPoint1 = ctrlPoint2 = new Config.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 Config.Point(line1.ctrlPoint1.x, line1.ctrlPoint1.y)
|
|
ocPoint2 = new Config.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
|
|
},
|
|
Config.getPointFromLine(x2, y2, x4, y4, tempDistence),
|
|
Config.getPointFromLine(x3, y3, x4, y4, tempDistence),
|
|
{
|
|
x: x3,
|
|
y: y3
|
|
}
|
|
]
|
|
}
|
|
//根据半径计算两条线段相切圆的圆心和切点坐标
|
|
this.getIncircleByLines = function (x1, y1, x2, y2, x3, y3, radius) {
|
|
//向量夹角
|
|
let angle = Config.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 = [Config.getPointFromLine(x1, y1, x2, y2, distance), Config.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 = Config.getPointArrOnLine(line.startPoint, line.endPoint)
|
|
} else {
|
|
pArr = Config.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 = Config.checkBoundary(new Config.Point(line2.startPoint.x, line2.startPoint.y), ptPolygon)
|
|
let ePoint = Config.checkBoundary(new Config.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 = Config.P_BEZ(0, sz)
|
|
for (let j = 0; j < 1; j += sp) {
|
|
p = Config.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 = Config.jie_cheng(n - 1)
|
|
let mother = Config.jie_cheng(i) * Config.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 Config.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 Config.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 Config.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 Config.Point(x0, y0))
|
|
}
|
|
}
|
|
return points
|
|
}
|
|
|
|
//转换公共设施type值
|
|
this.getFacType = function (str) {
|
|
let typeObj = {
|
|
ft: 0,
|
|
mys: 3,
|
|
xsj: 4,
|
|
dt: 5,
|
|
fwt: 7,
|
|
tcc: 8,
|
|
cjr: 10,
|
|
xys: 11,
|
|
ztg: 17,
|
|
thg: 18,
|
|
td: 20,
|
|
dit: 21,
|
|
czc: 22,
|
|
atm: 23,
|
|
jcfw: 24,
|
|
sjcd: 25,
|
|
bc: 26,
|
|
cjc: 27,
|
|
jtn: 28,
|
|
jtv: 29,
|
|
ksgj: 30,
|
|
sjxsn: 31,
|
|
sjxsv: 32,
|
|
tcjf: 33,
|
|
vip: 34,
|
|
xsjn: 35,
|
|
xsjv: 36,
|
|
yszj: 37,
|
|
xxt: 38,
|
|
door: 39,
|
|
pq: 40,
|
|
upft: 0,
|
|
downft: 0,
|
|
ysp: 50,
|
|
B1up: 51,
|
|
B1down: 52,
|
|
B2up: 53,
|
|
B2down: 54,
|
|
B3up: 55,
|
|
B3down: 56,
|
|
lt: 88,
|
|
xcgc: 57,
|
|
tthy: 58,
|
|
fwt2: 60,
|
|
syt2: 61,
|
|
syt1: 62,
|
|
gwc: 63,
|
|
fwt1: 64,
|
|
jrc: 65,
|
|
qbc: 66,
|
|
zxc: 67,
|
|
jws: 68,
|
|
etxsj: 69,
|
|
vip_xxq: 70,
|
|
ab: 71,
|
|
abjks: 72,
|
|
bys: 73,
|
|
cpgys: 74,
|
|
gzyld: 75,
|
|
hqgys: 76,
|
|
jjs: 77,
|
|
jw: 78,
|
|
ksj: 79,
|
|
kt: 80,
|
|
qzgysn: 81,
|
|
rsggys: 82,
|
|
swzl: 83,
|
|
tsgbs1: 84,
|
|
tsgbs2: 85,
|
|
tsgbs3: 86,
|
|
wxc: 87,
|
|
yhs: 89,
|
|
yls: 90,
|
|
ylz: 91,
|
|
ydygys: 92,
|
|
ydygysn: 93,
|
|
ydygysv: 94,
|
|
zls: 95,
|
|
zys: 96,
|
|
zas: 97,
|
|
xxq: 98,
|
|
jtxsj: 99,
|
|
hzs: 100,
|
|
brs: 101,
|
|
mtl: 102,
|
|
dgnxsj: 103,
|
|
wxbxsj: 104
|
|
}
|
|
return typeObj[str]
|
|
}
|
|
this.getFacName = function (str) {
|
|
let typeObj = {
|
|
ft: '扶梯',
|
|
mys: '母婴室',
|
|
xsj: '洗手间',
|
|
dt: '直梯',
|
|
fwt: '服务台',
|
|
tcc: '停车场',
|
|
cjr: '无障碍洗手间',
|
|
xys: '吸烟室',
|
|
dit: '地铁',
|
|
czc: '出租车',
|
|
atm: 'ATM',
|
|
jcfw: '寄存服务',
|
|
td: '人行通道',
|
|
sjcd: '手机充电',
|
|
bc: '泊车',
|
|
cjc: '裁剪处',
|
|
jtn: '家庭洗手间(男)',
|
|
jtv: '家庭洗手间(女)',
|
|
ksgj: '公交',
|
|
sjxsn: '男伤健人士洗手间',
|
|
sjxsv: '女伤健人士洗手间',
|
|
tcjf: '停车缴费',
|
|
vip: 'VIP',
|
|
xsjn: '男洗手间',
|
|
xsjv: '女洗手间',
|
|
yszj: '雨伞租借',
|
|
xxt: '信息台',
|
|
door: '出入口',
|
|
pq: '喷泉',
|
|
upft: '上扶梯',
|
|
downft: '下扶梯',
|
|
ysp: '艺术品',
|
|
lt: '楼梯',
|
|
xcgc: '下沉广场',
|
|
tthy: '天台花园',
|
|
fwt2: '超市服务台',
|
|
syt2: '超市收银台',
|
|
syt1: 'mall收银台',
|
|
gwc: '购物车',
|
|
fwt1: 'mall服务台',
|
|
jrc: '自助加热',
|
|
qbc: '自助取冰',
|
|
zxc: '自行车停放',
|
|
jws: '警务室',
|
|
etxsj: '儿童洗手间',
|
|
vip_xxq: 'vip休息区',
|
|
ab: '安保',
|
|
abjks: '安保监控室',
|
|
bys: '播音室',
|
|
cpgys: '裁判更衣室',
|
|
gzyld: '观众医疗点',
|
|
hqgys: '后勤更衣室',
|
|
jjs: '急救室',
|
|
jw: '警卫',
|
|
ksj: '开水间',
|
|
kt: '看台',
|
|
qzgysn: '亲自更衣(男)',
|
|
rsggys: '热身馆更衣室',
|
|
swzl: '失物招领',
|
|
tsgbs1: '特殊贵宾室1',
|
|
tsgbs2: '特殊贵宾室2',
|
|
tsgbs3: '特殊贵宾室3',
|
|
wxc: '闻讯处',
|
|
yhs: '医护室',
|
|
yls: '医疗室',
|
|
ylz: '医疗站',
|
|
ydygys: '运动员更衣室',
|
|
ydygysn: '运动员男更衣室',
|
|
ydygysv: '运动员女更衣室',
|
|
zls: '诊疗室',
|
|
zys: '直饮水',
|
|
zas: '治安室',
|
|
xxq: '休息区',
|
|
jtxsj: '家庭洗手间',
|
|
hzs: '化妆室',
|
|
brs: '哺乳室',
|
|
mtl: '摩天轮',
|
|
dgnxsj: '多功能洗手间',
|
|
wxbxsj: '无性别洗手间',
|
|
ztg: 'L1自提柜',
|
|
thg: 'B1自提柜'
|
|
}
|
|
return typeObj[str]
|
|
}
|
|
this.parkSort = function (a, b) {
|
|
return a.name < b.name ? -1 : 1
|
|
}
|
|
//店铺排序
|
|
this.sortShopByFloor = function (a, b) {
|
|
return a.floorOrder < b.floorOrder ? -1 : 1
|
|
}
|
|
//店铺排序
|
|
this.sortHouseNum = function (a, b) {
|
|
return a.houseNumber < b.houseNumber ? -1 : 1
|
|
}
|
|
|
|
this.sortNode = function (a, b) {
|
|
return a.id - b.id
|
|
}
|
|
|
|
/**该方法用来绘制一个圆角矩形
|
|
*@param cxt:canvas的上下文环境
|
|
*@param x:左上角x轴坐标
|
|
*@param y:左上角y轴坐标
|
|
*@param width:矩形的宽度
|
|
*@param height:矩形的高度
|
|
*@param radius:圆的半径
|
|
**/
|
|
this.drawRoundRectPath = function (cxt, width, height, radius) {
|
|
cxt.beginPath(0)
|
|
//从右下角顺时针绘制,弧度从0到1/2PI
|
|
cxt.arc(width - radius, height - radius, radius, 0, Math.PI / 2)
|
|
//矩形下边线
|
|
cxt.lineTo(radius, height)
|
|
//左下角圆弧,弧度从1/2PI到PI
|
|
cxt.arc(radius, height - radius, radius, Math.PI / 2, Math.PI)
|
|
//矩形左边线
|
|
cxt.lineTo(0, radius)
|
|
//左上角圆弧,弧度从PI到3/2PI
|
|
cxt.arc(radius, radius, radius, Math.PI, (Math.PI * 3) / 2)
|
|
//上边线
|
|
cxt.lineTo(width - radius, 0)
|
|
//右上角圆弧
|
|
cxt.arc(width - radius, radius, radius, (Math.PI * 3) / 2, Math.PI * 2)
|
|
//右边线
|
|
cxt.lineTo(width, height - radius)
|
|
cxt.closePath()
|
|
}
|
|
|
|
this.wordToSreen = function (world_vector) {
|
|
let vector = world_vector.project(Map_QM.camera)
|
|
let halfWidth = window.innerWidth / 2,
|
|
halfHeight = window.innerHeight / 2
|
|
return {
|
|
x: Math.round(vector.x * halfWidth + halfWidth),
|
|
y: Math.round(-vector.y * halfHeight + halfHeight)
|
|
}
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////////////////
|
|
this.getWallPoints = function (points, wallWidth) {
|
|
if (points.length < 2) {
|
|
//console.log("getWallPoints", "points size is letter than 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 = Config.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 = Config.getIntersectionByLines(start.leftParLine, end.leftParLine)
|
|
start.rightPoint = Config.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 Config.WallLine(start, end)
|
|
//计算当前线段的斜率
|
|
let gradient = (start.y - end.y) / (start.x - end.x)
|
|
//计算垂直线的斜率
|
|
let perGradient = -1 / gradient
|
|
//获取垂直线上左右两侧 与当前点位相距一定距离的两个定点
|
|
let startResult = Config.getParallelPoints(perGradient, start, wallWidth)
|
|
let endResult = Config.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 Config.WallLine(new Config.Point(x1, y1), new Config.Point(x2, y2))
|
|
line.rightParLine = new Config.WallLine(new Config.Point(x4, y4), new Config.Point(x5, y5))
|
|
} else {
|
|
line.leftParLine = new Config.WallLine(new Config.Point(x4, y4), new Config.Point(x5, y5))
|
|
line.rightParLine = new Config.WallLine(new Config.Point(x1, y1), new Config.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 = parseInt(gradient * (x - point.x) + point.y)
|
|
}
|
|
|
|
return Config.pointXY(point, new Config.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 Config.Point(curPoint.x, curPoint.y + length))
|
|
result.push(new Config.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 Config.Point(parseInt(x1), parseInt(k * x1 + b)))
|
|
result.push(new Config.Point(parseInt(x2), parseInt(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 Config.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 Config.Point(x, y)
|
|
}
|
|
/////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//计算点到线段的距离
|
|
this.PointToLineDistance = function (xx, yy, x1, y1, x2, y2) {
|
|
let ang1, ang2, ang, m
|
|
let result = 0
|
|
// 分别计算三条边的长度
|
|
const a = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy))
|
|
if (a === 0) {
|
|
return [0, { x: x1, y: y1 }]
|
|
}
|
|
const b = Math.sqrt((x2 - xx) * (x2 - xx) + (y2 - yy) * (y2 - yy))
|
|
if (b === 0) {
|
|
return [0, { x: x2, y: y2 }]
|
|
}
|
|
const c = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))
|
|
// 如果线段是一个点则退出函数并返回距离
|
|
if (c === 0) {
|
|
result = a
|
|
return [result, { x: x1, y: y1 }]
|
|
}
|
|
// 如果点(xx, yy到点x1, y1)这条边短
|
|
if (a < b) {
|
|
// 如果直线段AB是水平线。得到直线段AB的弧度
|
|
if (y1 === y2) {
|
|
if (x1 < x2) {
|
|
ang1 = 0
|
|
} else {
|
|
ang1 = Math.PI
|
|
}
|
|
} else {
|
|
m = (x2 - x1) / c
|
|
if (m - 1 > 0.00001) {
|
|
m = 1
|
|
}
|
|
ang1 = Math.acos(m)
|
|
if (y1 > y2) {
|
|
ang1 = Math.PI * 2 - ang1
|
|
} // 直线(x1, y1)-(x2, y2)与折X轴正向夹角的弧度
|
|
}
|
|
m = (xx - x1) / a
|
|
if (m - 1 > 0.00001) {
|
|
m = 1
|
|
}
|
|
ang2 = Math.acos(m)
|
|
if (y1 > yy) {
|
|
ang2 = Math.PI * 2 - ang2
|
|
} // 直线(x1, y1)-(xx, yy)与折X轴正向夹角的弧度
|
|
ang = ang2 - ang1
|
|
if (ang < 0) {
|
|
ang = -ang
|
|
}
|
|
if (ang > Math.PI) {
|
|
ang = Math.PI * 2 - ang
|
|
}
|
|
// 如果是钝角则直接返回距离
|
|
if (ang > Math.PI / 2) {
|
|
return [a, { x: x1, y: y1 }]
|
|
}
|
|
// 返回距离并且求得当前距离所在线段的坐标
|
|
if (x1 === x2) {
|
|
return [b * Math.sin(ang), { x: x1, y: yy }]
|
|
} else if (y1 === y2) {
|
|
return [b * Math.sin(ang), { x: xx, y: y1 }]
|
|
}
|
|
// 直线的斜率存在且不为0的情况下
|
|
let x = 0,
|
|
y = 0
|
|
const k1 = (y2 - y1) / x2 - x1
|
|
const kk = -1 / k1
|
|
const bb = yy - xx * kk
|
|
const b1 = y2 - x2 * k1
|
|
x = (b1 - bb) / (kk - k1)
|
|
y = kk * x + bb
|
|
return [a * Math.sin(ang), { x, y }]
|
|
}
|
|
// 如果两个点的纵坐标相同,则直接得到直线斜率的弧度
|
|
if (y1 === y2) {
|
|
if (x1 < x2) {
|
|
ang1 = Math.PI
|
|
} else {
|
|
ang1 = 0
|
|
}
|
|
} else {
|
|
m = (x1 - x2) / c
|
|
if (m - 1 > 0.00001) {
|
|
m = 1
|
|
}
|
|
ang1 = Math.acos(m)
|
|
if (y2 > y1) {
|
|
ang1 = Math.PI * 2 - ang1
|
|
}
|
|
}
|
|
m = (xx - x2) / b
|
|
if (m - 1 > 0.00001) {
|
|
m = 1
|
|
}
|
|
ang2 = Math.acos(m) // 直线(x2-x1)-(xx, yy)斜率的弧度
|
|
if (y2 > yy) {
|
|
ang2 = Math.PI * 2 - ang2
|
|
}
|
|
ang = ang2 - ang1
|
|
if (ang < 0) {
|
|
ang = -ang
|
|
}
|
|
if (ang > Math.PI) {
|
|
ang = Math.PI * 2 - ang
|
|
} // 交角的大小
|
|
// 如果是对角则直接返回距离
|
|
if (ang > Math.PI / 2) {
|
|
return [b, { x: x2, y: y2 }]
|
|
}
|
|
// 如果是锐角,返回计算得到的距离,并计算出相应的坐标
|
|
if (x1 === x2) {
|
|
return [b * Math.sin(ang), { x: x1, y: yy }]
|
|
} else if (y1 === y2) {
|
|
return [b * Math.sin(ang), { x: xx, y: y1 }]
|
|
}
|
|
// 直线的斜率存在且不为0的情况下
|
|
let x = 0,
|
|
y = 0
|
|
const k1 = (y2 - y1) / x2 - x1
|
|
const kk = -1 / k1
|
|
const bb = yy - xx * kk
|
|
const b1 = y2 - x2 * k1
|
|
x = (b1 - bb) / (kk - k1)
|
|
y = kk * x + bb
|
|
return [b * Math.sin(ang), { x, y }]
|
|
}
|
|
//点到直线距离
|
|
this.PointToLineDis = function (xx, yy, x1, y1, x2, y2) {
|
|
let len
|
|
if (x1 - x2 == 0) {
|
|
len = Math.abs(xx - x1)
|
|
} else {
|
|
let A = (y1 - y2) / (x1 - x2)
|
|
let B = y1 - A * x1
|
|
len = Math.abs((A * xx + B - yy) / Math.sqrt(A * A + 1))
|
|
}
|
|
return len
|
|
}
|
|
|
|
this.getShopData = function (callBack, shopData) {
|
|
let backObj = { code: 200, msg: '加载成功', data: [] }
|
|
if (shopData) {
|
|
Config.shopData = shopData.shopList
|
|
if (Config.shopData && Array.isArray(Config.shopData)) {
|
|
Config.shopData.sort(Config.sortShopByFloor)
|
|
try {
|
|
if (!Map_QM) {
|
|
Map_QM = new MainMap_QM(callBack, backObj)
|
|
Map_QM.initBuild()
|
|
} else {
|
|
Map_QM.callBackLoadOver = callBack
|
|
Map_QM.backObj = backObj
|
|
Map_QM.loaderOver()
|
|
}
|
|
} catch (e) {
|
|
console.log(e)
|
|
callBack({ code: 404, msg: '地图数据解析失败' })
|
|
callBack = null
|
|
}
|
|
} else {
|
|
backObj.code = 500
|
|
backObj.msg = '店铺数据错误'
|
|
}
|
|
if (backObj.code == 404) {
|
|
callBack(backObj)
|
|
}
|
|
} else {
|
|
backObj.code = 500
|
|
backObj.msg = '店铺数据错误'
|
|
callBack(backObj)
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////---------------------------end
|
|
/**
|
|
* 根据色值获取材质
|
|
*/
|
|
this.getMeshMaterial = function (color, alphaModle = 0.9) {
|
|
let meshMaterial
|
|
for (let k = 0; k < Config.meshMaterialArr.length; k++) {
|
|
let color2 = new THREE.Color(color)
|
|
if (Config.meshMaterialArr[k].color.equals(color2) && Config.meshMaterialArr[k].opacity == alphaModle) {
|
|
meshMaterial = Config.meshMaterialArr[k]
|
|
}
|
|
}
|
|
if (!meshMaterial) {
|
|
meshMaterial = new THREE.MeshPhongMaterial({
|
|
color: color,
|
|
emissive: 0x000000,
|
|
specular: 0x000000,
|
|
transparent: true,
|
|
side: THREE.DoubleSide,
|
|
opacity: alphaModle
|
|
})
|
|
Config.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)
|
|
}
|
|
this.rotateTextYZ = function (geometry, rx, 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.rotateX(rx)
|
|
geometry.rotateY(ry)
|
|
geometry.rotateZ(rz)
|
|
geometry.translate(x, y, z)
|
|
}
|
|
//对象克隆
|
|
this.cloneObject = function (sourceObj) {
|
|
let target = sourceObj instanceof Array ? [] : {}
|
|
for (attr in sourceObj) {
|
|
if (!obj.hasOwnProperty(attr)) continue
|
|
target[attr] = typeof sourceObj[i] == 'object' ? obj[attr].clone() : obj[attr]
|
|
}
|
|
return target
|
|
}
|
|
}
|
|
var Config = new ConfigFun()
|
|
|
|
//////////////////////////////-------------------------------------------配置 ConfigFun
|
|
/**
|
|
* 地图主类,入口 初始化设备点位
|
|
* @param width,height 勾图的地图宽、高
|
|
* @param floor, 楼层编号从0开始
|
|
* @param navPoint, 导航点位
|
|
* @param angle(-180~180) 设备角度
|
|
*/
|
|
MainMap_QM = function (callBack, backObj) {
|
|
this.callBackLoadOver = callBack
|
|
this.backObj = backObj
|
|
let ele = document.getElementById('mapContainer')
|
|
|
|
this.w = parseInt(window.getComputedStyle(ele, null).getPropertyValue('width'))
|
|
this.h = parseInt(window.getComputedStyle(ele, null).getPropertyValue('height'))
|
|
this.scene = new THREE.Scene()
|
|
this.scene.name = 'scene'
|
|
|
|
aspect = this.w / this.h
|
|
cameraPerspective = new THREE.PerspectiveCamera(45, aspect, 10, 10000)
|
|
cameraPerspective.position.set(Config.cameraDist.x, Config.cameraDist.y, Config.cameraDist.z) //x 水平 y 垂直旋转 z 展示大小
|
|
cameraPerspective.lookAt(new THREE.Vector3(0, 0, 0))
|
|
|
|
cameraOrtho = new THREE.OrthographicCamera((340 * aspect) / -2, (340 * aspect) / 2, 340 / 2, 340 / -2, 10, 10000)
|
|
cameraOrtho.position.set(0, 200, 0)
|
|
cameraOrtho.lookAt(new THREE.Vector3(0, 0, 0))
|
|
this.camera = Config.cameraDist.state == '2D' ? cameraOrtho : 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 = true
|
|
// 阴影类型
|
|
this.renderer.shadowMap.type = THREE.PCFSoftShadowMap
|
|
ele.appendChild(this.renderer.domElement)
|
|
this.renderer.domElement.style.width = this.w
|
|
this.renderer.domElement.style.height = this.h
|
|
|
|
this.labelRenderer = new THREE.CSS2DRenderer()
|
|
this.labelRenderer.setSize(this.w, this.h, Config.perc_H)
|
|
this.labelRenderer.domElement.style.position = 'absolute'
|
|
this.labelRenderer.domElement.style.top = 0
|
|
ele.appendChild(this.labelRenderer.domElement)
|
|
|
|
let aLight = new THREE.AmbientLight(0xffffff, 0.3)
|
|
aLight.name = 'light'
|
|
this.scene.add(aLight)
|
|
|
|
let hemiLight = new THREE.HemisphereLight(0xdddddd, 0xffffff, 0.56)
|
|
hemiLight.position.set(0, 50, 0)
|
|
hemiLight.name = 'light'
|
|
this.scene.add(hemiLight)
|
|
|
|
let directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.3)
|
|
directionalLight2.name = 'light'
|
|
directionalLight2.position.set(280, 400, -300)
|
|
if (Config.cameraDist.state === '3D') {
|
|
directionalLight2.castShadow = true //阴影
|
|
directionalLight2.shadow.camera.top = 320
|
|
directionalLight2.shadow.camera.bottom = -320
|
|
directionalLight2.shadow.camera.right = 320
|
|
directionalLight2.shadow.camera.left = -320
|
|
directionalLight2.shadow.camera.far = 1200
|
|
directionalLight2.shadow.camera.near = 50
|
|
directionalLight2.shadow.mapSize.set(1024, 1024)
|
|
}
|
|
this.scene.add(directionalLight2)
|
|
|
|
this.mixers = []
|
|
this.controls = new THREE.OrbitControls(this.camera, 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 = Config.cameraZoom
|
|
//设置相机距离原点的最远距离
|
|
this.controls.minDistance = Config.mapDistance.min
|
|
//设置相机距离原点的最远距离
|
|
this.controls.maxDistance = Config.mapDistance.max
|
|
this.controls.minPolarAngle = Config.cameraDist.state == '2D' ? 0 : 0.3 // radians
|
|
this.controls.maxPolarAngle = Config.cameraDist.state == '2D' ? 0 : Math.PI / 2 - 0.3 // radians
|
|
|
|
this.controls.addEventListener('change', this.collisionChock, false) //控制器变化
|
|
if (window.PointerEvent) {
|
|
document.getElementById('mapContainer').addEventListener('pointerup', this.onMouseClickBox, false) //地图点击
|
|
} else {
|
|
document.getElementById('mapContainer').addEventListener('click', this.onMouseClickBox, false) //地图点击
|
|
}
|
|
document.addEventListener('rezise', this.changeWindowResize, false) //窗口变化
|
|
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')) {
|
|
this.moveFloorbg = new THREE.CSS2DObject(document.getElementById('moveFloorBG'))
|
|
this.scene.add(this.moveFloorbg)
|
|
}
|
|
this.man_3d
|
|
this.man_2d
|
|
this.guide
|
|
this.sceneGap = new THREE.Group()
|
|
this.outModelGap = new THREE.Group() //全局外立面模型
|
|
this.scene.add(this.outModelGap)
|
|
|
|
this.qiModel //起点
|
|
this.qiIcon //起点Icon
|
|
this.dirIcon //我的方向Icon
|
|
this.endIcon //终点Icon
|
|
this.endModel
|
|
this.forShopArr = [] //途径数据
|
|
}
|
|
MainMap_QM.prototype = {
|
|
//加载全局模型
|
|
initOutModel: function () {
|
|
if (Config.initModelArr && Config.initModelArr.length > 0) {
|
|
for (let i = 0; i < Config.initModelArr.length; i++) {
|
|
let loader = new THREE.GLTFLoader()
|
|
loader.load(Config.initModelArr[i].url, function (collada) {
|
|
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = Config.initModelArr[i].scale
|
|
collada.scene.position.set(Config.initModelArr[i].site.x, Config.initModelArr[i].site.y, Config.initModelArr[i].site.z)
|
|
collada.scene.rotation.set(
|
|
(Config.initModelArr[i].rot.x * Math.PI) / 180,
|
|
(Config.initModelArr[i].rot.y * Math.PI) / 180,
|
|
(Config.initModelArr[i].rot.z * Math.PI) / 180
|
|
)
|
|
collada.scene.userData.type = Config.initModelArr[i].type
|
|
collada.scene.traverse(function (child) {
|
|
if (child.type === 'Mesh') {
|
|
child.castShadow = true
|
|
child.receiveShadow = true
|
|
if (child.material.map) {
|
|
child.material.map.encoding = THREE.LinearEncoding //贴图需要转换成 线性编码
|
|
}
|
|
child.material.color.convertGammaToLinear(0.7)
|
|
}
|
|
})
|
|
collada.scene.name = 'model' //删除其它元素时过滤
|
|
Map_QM.outModelGap.add(collada.scene)
|
|
// 添加进入商场标签
|
|
let SpriteDiv = document.createElement('div')
|
|
SpriteDiv.style = "position: absolute; background: url('./static/img/map-btn-bg.png'); width: 220px; height: 64px;"
|
|
SpriteDiv.innerHTML =
|
|
'<p style="position: absolute; top: 4px; left: 12px; text-align: center; line-height: 30px; color: #FFFFFF; font-size: 20px; font-weight: bold;">建发现代城</p>' +
|
|
'<p style="position: absolute; top: 34px; left: 12px; text-align: center; line-height: 18px; color: #FFFFFF; font-size: 12px;" >购物中心</p>' +
|
|
'<p class="toMallBtn" style="position: absolute;top: 8px; right: 8px; width: 42px; height: 42px;background: #E14E69;border-radius: 4px; text-align: center;line-height: 42px;color: #FFFFFF;font-size: 14px;font-weight: bold;" onclick="Map_QM.goHome(event)">进入</p>' +
|
|
'<img src="./static/img/gray-icon.png" style="position: absolute; bottom: -17px; left: 50%; transform: translateX(-50%); margin-top: 4px;" alt="">'
|
|
let pointLabel = new THREE.CSS2DObject(SpriteDiv)
|
|
pointLabel.position.set(-7.2, -30, 0.2)
|
|
pointLabel.userData.type = '2d_IP'
|
|
pointLabel.center = new THREE.Vector2(0.5, 0)
|
|
pointLabel.userData.show = 'cn'
|
|
Map_QM.outModelGap.add(pointLabel)
|
|
if (pointLabel.userData.show != language) {
|
|
pointLabel.element.style.opacity = 0
|
|
}
|
|
|
|
let SpriteDiv2 = document.createElement('div')
|
|
SpriteDiv2.style = "position: absolute; background: url('./static/img/map-btn-bg.png'); width: 220px; height: 64px;"
|
|
SpriteDiv2.innerHTML =
|
|
'<p style="position: absolute; top: 4px; left: 12px; text-align: center; line-height: 30px; color: #FFFFFF; font-size: 20px; font-weight: bold;">MODERN CITY</p>' +
|
|
'<p style="position: absolute; top: 34px; left: 12px; text-align: center; line-height: 18px; color: #FFFFFF; font-size: 12px;" >Shopping Mall</p>' +
|
|
'<p class="toMallBtn" style="position: absolute;top: 8px; right: 8px; width: 42px; height: 42px;background: #E14E69;border-radius: 4px; text-align: center;line-height: 42px;color: #FFFFFF;font-size: 14px;font-weight: bold;" onclick="Map_QM.goHome(event)">GO</p>' +
|
|
'<img src="./static/img/gray-icon.png" style="position: absolute; bottom: -17px; left: 50%; transform: translateX(-50%); margin-top: 4px;" alt="">'
|
|
let pointLabel2 = new THREE.CSS2DObject(SpriteDiv2)
|
|
pointLabel2.position.set(-7.2, -30, 0.2)
|
|
pointLabel2.userData.type = '2d_IP'
|
|
pointLabel2.center = new THREE.Vector2(0.5, 0)
|
|
pointLabel2.userData.show = 'en'
|
|
Map_QM.outModelGap.add(pointLabel2)
|
|
if (pointLabel2.userData.show != language) {
|
|
pointLabel2.element.style.opacity = 0
|
|
}
|
|
})
|
|
if (i == Config.initModelArr.length - 1) {
|
|
Map_QM.initBuild()
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
initBuild: function (e) {
|
|
console.log('******')
|
|
elevator = null
|
|
straight = null
|
|
elevatorDown = null
|
|
if (Config.showModelIcon) {
|
|
let loader = new THREE.GLTFLoader()
|
|
loader.load('./static/img/elevator.gltf', function (collada) {
|
|
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = 15
|
|
collada.scene.rotation.x = (-90 * Math.PI) / -180
|
|
collada.scene.renderOrder = 300
|
|
elevator = collada.scene
|
|
collada.scene.children[0].traverse(function (child) {
|
|
if (child.isMesh && child.name == 'boli2') {
|
|
//child.material.color = new THREE.Color(0xffffff);
|
|
child.material.opacity = 0.8
|
|
}
|
|
if (child.isMesh && child.name == 'pidai') {
|
|
//child.material.color = new THREE.Color(0xffffff);
|
|
child.material.opacity = 0.8
|
|
}
|
|
})
|
|
new THREE.GLTFLoader().load('./static/img/elevatorDown.gltf', function (collada) {
|
|
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = 15
|
|
collada.scene.rotation.x = (-90 * Math.PI) / -180
|
|
collada.scene.renderOrder = 300
|
|
elevatorDown = collada.scene
|
|
collada.scene.children[0].traverse(function (child) {
|
|
if (child.isMesh && child.name == 'boli2') {
|
|
//child.material.color = new THREE.Color(0xffffff);
|
|
child.material.opacity = 0.8
|
|
}
|
|
if (child.isMesh && child.name == 'pidai') {
|
|
//child.material.color = new THREE.Color(0xffffff);
|
|
child.material.opacity = 0.8
|
|
}
|
|
})
|
|
|
|
new THREE.GLTFLoader().load('./static/img/dt.gltf', function (collada) {
|
|
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = 15
|
|
collada.scene.rotation.x = (-90 * Math.PI) / -180
|
|
collada.scene.renderOrder = 300
|
|
straight = collada.scene
|
|
//console.log(straight);
|
|
straight.traverse(function (child) {
|
|
if (child.isMesh && child.name == 'zhitiboli') {
|
|
//child.material.color = new THREE.Color(0xffffff);
|
|
child.material.opacity = 0.6
|
|
child.material.side = 1
|
|
}
|
|
// if (child.isMesh && child.name == "zhitijiegou") {
|
|
// child.material.color = new THREE.Color(0xffffff);
|
|
// child.material.opacity = 0.8;
|
|
// }
|
|
})
|
|
Map_QM.index = 0
|
|
Map_QM.initTreeModel()
|
|
})
|
|
})
|
|
})
|
|
} else {
|
|
Map_QM.index = 0
|
|
Map_QM.initTreeModel()
|
|
}
|
|
},
|
|
loaderOver: function (e) {
|
|
Map_QM.cancelRender()
|
|
this.controls.reset()
|
|
basePath = null
|
|
this.renderer.dispose()
|
|
this.remove_child(this.sceneGap)
|
|
this.scene.remove(this.sceneGap)
|
|
this.sceneGap = new THREE.Group()
|
|
this.sceneGap.position.set(Config.sceneGap.x, Config.sceneGap.y, Config.sceneGap.z)
|
|
this.sceneGap.scale.set(Config.sceneGap.scale, Config.sceneGap.scale, Config.sceneGap.scale)
|
|
this.scene.add(this.sceneGap)
|
|
this.buildObj = new THREE.Group()
|
|
this.sceneGap.add(this.buildObj)
|
|
this.CSSObject = new THREE.Object3D()
|
|
this.buildObj.add(this.CSSObject)
|
|
this.buildObj.add(this.dtLineGroup)
|
|
this.initGuide()
|
|
|
|
let pathData = Config.allMap[parseInt(Config.deviceObj.build)].buildArr[parseInt(Config.deviceObj.floor)].mapData.path
|
|
if (parseInt(Config.deviceObj.node) != -1) {
|
|
if (pathData && pathData.nodes.length > parseInt(Config.deviceObj.node)) {
|
|
Config.deviceObj.xaxis = pathData.nodes[parseInt(Config.deviceObj.node)].x
|
|
Config.deviceObj.yaxis = pathData.nodes[parseInt(Config.deviceObj.node)].y
|
|
}
|
|
}
|
|
|
|
Config.mapScale = Config.allMap[Config.selectBuild].scale || 18
|
|
facAllArr = []
|
|
this.mapArr.length = 0
|
|
basePath = '{'
|
|
for (let bd = 0; bd < Config.allMap.length; bd++) {
|
|
for (let i = 0; i < Config.allMap[bd].buildArr.length; i++) {
|
|
this.convertPath(bd, i)
|
|
}
|
|
}
|
|
if (basePath.length > 1) {
|
|
basePath = basePath.substr(0, basePath.length - 1)
|
|
}
|
|
if (Config.otherPath) {
|
|
//如果多楼栋需要配置楼栋之间通行路径
|
|
basePath += Config.otherPath
|
|
}
|
|
basePath += '}'
|
|
//初始化基础路径;
|
|
let graphPathObj = JSON.parse(basePath)
|
|
let ftPathObj = JSON.parse(basePath)
|
|
let dtPathObj = JSON.parse(basePath)
|
|
for (let j = 0; j < facAllArr.length; j++) {
|
|
for (let k = 0; k < facAllArr[j].length; k++) {
|
|
let facP = facAllArr[j][k].buildOrder + '_' + facAllArr[j][k].floorOrder + '_' + facAllArr[j][k].navCode
|
|
for (let h = 0; h < facAllArr[j].length; h++) {
|
|
if (h != k) {
|
|
let nP = facAllArr[j][h].buildOrder + '_' + facAllArr[j][h].floorOrder + '_' + facAllArr[j][h].navCode
|
|
if (facAllArr[j][h].facCode == 'dt') {
|
|
ftPathObj[facP][nP] = 6000
|
|
if (facAllArr[j][k].selFac) {
|
|
graphPathObj[facP][nP] = 300 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
dtPathObj[facP][nP] = 300 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
} else {
|
|
graphPathObj[facP][nP] = 1500 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
dtPathObj[facP][nP] = 1500 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
}
|
|
} else if (facAllArr[j][h].facCode == 'lt') {
|
|
graphPathObj[facP][nP] = 500 + 300 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
ftPathObj[facP][nP] = 500 + 300 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
dtPathObj[facP][nP] = 500 + 300 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
} else {
|
|
dtPathObj[facP][nP] = 6000
|
|
if (facAllArr[j][k].selFac) {
|
|
graphPathObj[facP][nP] = 300 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
ftPathObj[facP][nP] = 300 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
} else {
|
|
graphPathObj[facP][nP] = 1500 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
ftPathObj[facP][nP] = 1500 + 100 * Math.abs(parseInt(facAllArr[j][h].floorOrder) - parseInt(facAllArr[j][k].floorOrder))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
graphPath = graphPathObj
|
|
ftPath = ftPathObj
|
|
dtPath = dtPathObj
|
|
var fIndex = 0,
|
|
bIndex = 0
|
|
this.mapArr[bIndex] = []
|
|
intTimer = setInterval(() => {
|
|
let floor = new FloorMap_QM(bIndex, fIndex, Config.allMap[bIndex].buildArr[fIndex].name)
|
|
floor.floorName = Config.allMap[bIndex].buildArr[fIndex].name
|
|
floor.initDraw()
|
|
floor.allObj.position.set(bIndex * Config.distance, (fIndex - Config.selectFloor) * Config.doubleDist, 0)
|
|
//floor.allObj.renderOrder = 20 - fIndex;
|
|
this.buildObj.add(floor.allObj)
|
|
this.mapArr[bIndex].push(floor)
|
|
fIndex++
|
|
if (fIndex >= Config.allMap[bIndex].buildArr.length) {
|
|
if (bIndex == Config.allMap.length - 1) {
|
|
clearInterval(intTimer)
|
|
this.controls.minPan = new THREE.Vector3(this.w / -10, 0, this.h / -10)
|
|
this.controls.maxPan = new THREE.Vector3(this.w / 10, 0, this.h / 10)
|
|
let pathData = Config.allMap[parseInt(Config.deviceObj.build)].buildArr[parseInt(Config.deviceObj.floor)].mapData.path
|
|
if (Config.deviceObj.xaxis) {
|
|
Map_QM.mapArr[parseInt(Config.deviceObj.build)][parseInt(Config.deviceObj.floor)].setStartSite(
|
|
Config.deviceObj.xaxis,
|
|
Config.deviceObj.yaxis,
|
|
parseInt(Config.shopHeight)
|
|
)
|
|
} else {
|
|
if (parseInt(Config.deviceObj.node) != -1) {
|
|
if (pathData && !Config.deviceObj.xaxis && pathData.nodes.length > parseInt(Config.deviceObj.node)) {
|
|
Config.deviceObj.xaxis = pathData.nodes[parseInt(Config.deviceObj.node)].x
|
|
Config.deviceObj.yaxis = pathData.nodes[parseInt(Config.deviceObj.node)].y
|
|
} else {
|
|
console.warn('初始化点位失败')
|
|
}
|
|
Map_QM.mapArr[parseInt(Config.deviceObj.build)][parseInt(Config.deviceObj.floor)].setStartSite(
|
|
Config.deviceObj.xaxis,
|
|
Config.deviceObj.yaxis,
|
|
parseInt(Config.shopHeight)
|
|
)
|
|
}
|
|
}
|
|
this.initFloor()
|
|
} else {
|
|
bIndex++
|
|
fIndex = 0
|
|
this.mapArr[bIndex] = []
|
|
}
|
|
}
|
|
}, 50)
|
|
},
|
|
initTreeModel: function () {
|
|
let url = Config.modelStr[this.index].url
|
|
this.gltfLoad(url)
|
|
},
|
|
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 = true
|
|
child.receiveShadow = true
|
|
if (child.material.map) {
|
|
child.material.map.encoding = THREE.LinearEncoding //贴图需要转换成 线性编码
|
|
}
|
|
if (Config.modelStr[sopce.index].colorModel === 'gama') {
|
|
child.material.color.convertGammaToLinear(0.5)
|
|
}
|
|
}
|
|
})
|
|
object.scene.children[0].scale.set(Config.modelStr[sopce.index].size.x, Config.modelStr[sopce.index].size.y, Config.modelStr[sopce.index].size.z)
|
|
Config.fbxModels.push({ key: Config.modelStr[sopce.index].key, obj: object.scene, operation: Config.modelStr[sopce.index] })
|
|
if (sopce.index < Config.modelStr.length - 1) {
|
|
sopce.index++
|
|
sopce.initTreeModel()
|
|
} else {
|
|
if (Config.allMap && Config.allMap.length > 0) {
|
|
Map_QM.loaderOver()
|
|
} else {
|
|
Config.getInstance(Map_QM.callBackLoadOver, Config.deviceObj.build, Config.deviceObj.floor, Config.deviceObj.node, Config.deviceObj.angle)
|
|
}
|
|
}
|
|
})
|
|
},
|
|
initGuide: function () {
|
|
new THREE.GLTFLoader().load('./static/img/runman.gltf', function (obj) {
|
|
obj.scene.scale.x = obj.scene.scale.y = obj.scene.scale.z = 15
|
|
obj.scene.children[0].children[1].children[0].material.color = new THREE.Color(0xfe9219)
|
|
Map_QM.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()
|
|
Map_QM.mixers.push(mixer)
|
|
Map_QM.man_3d = obj.scene
|
|
Map_QM.guide = Map_QM.man_3d
|
|
})
|
|
|
|
new THREE.TextureLoader().load('./static/img/guide.png', textu => {
|
|
let planeMaterial = new THREE.MeshPhongMaterial({
|
|
map: textu,
|
|
depthTest: true,
|
|
transparent: true,
|
|
alphaTest: 0.1
|
|
})
|
|
let planeGeometry = new THREE.PlaneGeometry(128, 128)
|
|
Map_QM.man_2d = new THREE.Mesh(planeGeometry, planeMaterial)
|
|
Map_QM.man_2d.center = new THREE.Vector2(0.5, 0.5)
|
|
Map_QM.man_2d.visible = false
|
|
Map_QM.sceneGap.add(Map_QM.man_2d)
|
|
})
|
|
},
|
|
initFloor: function () {
|
|
Map_QM.changeFloorInner()
|
|
//初始化方向为第一人称方向
|
|
let angle = Config.deviceAng ? Config.deviceObj.angle : Config.mapAngle
|
|
Map_QM.rotationAngle(angle)
|
|
Map_QM.startRender()
|
|
Map_QM.controls.saveState()
|
|
},
|
|
/**
|
|
* 解析路径
|
|
*/
|
|
convertPath: function (buildOrder, floorOrder) {
|
|
let mapData = Config.allMap[buildOrder].buildArr[floorOrder].mapData
|
|
let pathData = mapData.path
|
|
if (!pathData) {
|
|
return
|
|
}
|
|
if (pathData.nodes.length > 0) {
|
|
pathData.nodes.sort(Config.sortNode)
|
|
for (let i = 0; i < pathData.nodes.length; i++) {
|
|
let a = pathData.nodes[i].id
|
|
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
|
|
}
|
|
basePath += '"' + buildOrder + '_' + floorOrder + '_' + b + '":' + pathData.nodes[i]['list'][n].cost + ','
|
|
}
|
|
if (pathData.nodes[i]['list'].length > 0) {
|
|
basePath = basePath.substr(0, basePath.length - 1)
|
|
}
|
|
basePath += '},'
|
|
}
|
|
}
|
|
let selUpFacNo = -1,
|
|
selDownFacNo = -1,
|
|
seldtFacNo = -1,
|
|
minupS = -1,
|
|
mindownS = -1,
|
|
minds = -1,
|
|
minls = -1
|
|
for (let h = 0; h < mapData.stairs.length; h++) {
|
|
mapData.stairs[h].selFac = false
|
|
if (mapData.stairs[h].state && mapData.stairs[h].no != '') {
|
|
let ms = Math.abs(parseInt(mapData.stairs[h].x) - parseInt(Config.deviceObj.xaxis)) + Math.abs(parseInt(mapData.stairs[h].y) - parseInt(Config.deviceObj.yaxis))
|
|
if (mapData.stairs[h].facCode.search('ft') != -1) {
|
|
if (mapData.stairs[h].facCode == 'upft') {
|
|
if (minupS == -1) {
|
|
minupS = ms
|
|
selUpFacNo = mapData.stairs[h].no
|
|
} else {
|
|
if (minupS > ms) {
|
|
minupS = ms
|
|
selUpFacNo = mapData.stairs[h].no
|
|
}
|
|
}
|
|
} else {
|
|
if (mindownS == -1) {
|
|
mindownS = ms
|
|
selDownFacNo = mapData.stairs[h].no
|
|
} else {
|
|
if (mindownS > ms) {
|
|
mindownS = ms
|
|
selDownFacNo = mapData.stairs[h].no
|
|
}
|
|
}
|
|
}
|
|
} else if (mapData.stairs[h].facCode == 'dt') {
|
|
if (minds == -1) {
|
|
minds = ms
|
|
seldtFacNo = mapData.stairs[h]
|
|
} else {
|
|
if (minds > ms) {
|
|
minds = ms
|
|
seldtFacNo = mapData.stairs[h]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
seldtFacNo.selFac = true
|
|
selUpFacNo.selFac = true
|
|
selDownFacNo.selFac = true
|
|
|
|
let noHas
|
|
for (let j = 0; j < mapData.stairs.length; j++) {
|
|
if ((mapData.stairs[j].hasOwnProperty('state') && mapData.stairs[j].state) || !mapData.stairs[j].state) {
|
|
//排除禁用的设施
|
|
noHas = true
|
|
for (let k = 0; k < facAllArr.length; k++) {
|
|
//facAllArr 记录遍历结果
|
|
if (facAllArr[k][0].no != '' && facAllArr[k][0].navCode != '' && facAllArr[k][0].no == mapData.stairs[j].no) {
|
|
if (facAllArr[k][0].facCode == mapData.stairs[j].facCode || (facAllArr[k][0].facCode.search('ft') != -1 && mapData.stairs[j].facCode.search('ft') != -1)) {
|
|
noHas = false
|
|
mapData.stairs[j].floorOrder = floorOrder
|
|
mapData.stairs[j].buildOrder = buildOrder
|
|
facAllArr[k].push(mapData.stairs[j])
|
|
}
|
|
}
|
|
}
|
|
if (noHas) {
|
|
mapData.stairs[j].buildOrder = buildOrder
|
|
mapData.stairs[j].floorOrder = floorOrder
|
|
let array = [mapData.stairs[j]]
|
|
facAllArr.push(array)
|
|
}
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} changeMapState("3d") 地图状态切换
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 地图展示状态切换
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {string} state 地图状态
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.changeMapState("2d");
|
|
*
|
|
*/
|
|
changeMapState: function (state) {
|
|
if (state === '3d') {
|
|
Map_QM.camera = cameraPerspective
|
|
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.3
|
|
Map_QM.controls.minPolarAngle = 0.3
|
|
Map_QM.controls.object = Map_QM.camera
|
|
Map_QM.camera.updateProjectionMatrix() //必须update
|
|
Map_QM.camera.position.set(Config.cameraDist.x, Config.cameraDist.y, Config.cameraDist.z)
|
|
Map_QM.changeIconState(state)
|
|
} else {
|
|
Map_QM.camera = cameraOrtho
|
|
Map_QM.controls.maxPolarAngle = 0
|
|
Map_QM.controls.minPolarAngle = 0
|
|
Map_QM.controls.object = Map_QM.camera
|
|
Map_QM.camera.updateProjectionMatrix() //必须update
|
|
Map_QM.controls.maxPolarAngle = 0
|
|
Map_QM.changeIconState(state)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api {方法} changeIconState("3d") ICON状态切换
|
|
* @apiGroup 地图交互
|
|
* @apiDescription ICON状态切换
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {string} state 展示状态
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.changeIconState("2d");
|
|
*
|
|
*/
|
|
changeIconState: function (state) {
|
|
for (let i = 0; i < Map_QM.mapArr[Config.selectBuild].length; i++) {
|
|
Map_QM.mapArr[Config.selectBuild][i].serObj.traverse(obj => {
|
|
if (obj.userData && obj.userData.use) {
|
|
if (obj.userData.use != 'all' && obj.userData.use != state) {
|
|
obj.visible = false
|
|
} else {
|
|
obj.visible = true
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
if (Map_QM.dirIcon) {
|
|
Map_QM.dirIcon.visible = state == '2d' ? true : false
|
|
}
|
|
if (Map_QM.qiModel) {
|
|
Map_QM.qiModel.visible = state == '2d' ? false : true
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api {方法} changeBuild(0) 楼栋切换
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 楼栋切换 传入楼栋编号
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} index 传入楼栋编号,改变地图显示内容
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {int} 请求示例
|
|
*
|
|
* Map_QM.changeBuild(0);
|
|
*
|
|
*/
|
|
changeBuild: function (fIndex = -1, tFloor = 0) {
|
|
clearTimeout(outTime)
|
|
Map_QM.forShopArr.length = 0
|
|
forShopArr = { direction: '', wayList: [] }
|
|
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
|
|
}
|
|
Map_QM.clearFloor(Config.selectFloor)
|
|
if (fIndex != -1) {
|
|
Config.selectBuild = fIndex
|
|
Config.selectFloor = tFloor
|
|
}
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.visible = true
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].labelObj.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].iconLabel.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
TweenMax.to(Map_QM.buildObj.position, 0.3, {
|
|
x: Config.selectBuild * Config.distance * -1,
|
|
onComplete: function () {
|
|
Map_QM.changeFloorInner(Config.selectFloor) //结束后切换楼层
|
|
}
|
|
})
|
|
},
|
|
/**
|
|
* @api {方法} onShowMeDir() 我的方向
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 我的方向
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.onShowMeDir();
|
|
*
|
|
*/
|
|
onShowMeDir: function (zoom = 0) {
|
|
Config.setModelState('2d')
|
|
Map_QM.camera = cameraOrtho
|
|
Map_QM.controls.maxPolarAngle = 0
|
|
Map_QM.controls.minPolarAngle = 0
|
|
if (isPathState) {
|
|
Map_QM.dirIcon.visible = false
|
|
Map_QM.qiIcon.visible = true
|
|
}
|
|
Map_QM.controls.object = Map_QM.camera
|
|
if (Config.deviceObj.xaxis) {
|
|
Map_QM.controls.object.position.set(Config.deviceObj.xaxis * Config.sceneGap.scale, 100, Config.deviceObj.yaxis * Config.sceneGap.scale)
|
|
Map_QM.controls.target = new THREE.Vector3(Config.deviceObj.xaxis * Config.sceneGap.scale, 0, Config.deviceObj.yaxis * Config.sceneGap.scale)
|
|
} else {
|
|
Map_QM.controls.object.position.set(0, 100, 0)
|
|
Map_QM.controls.target = new THREE.Vector3(0, 0, 0)
|
|
}
|
|
zoom = zoom == 0 ? Config.cameraZoom : zoom
|
|
Map_QM.controls.setZoom(zoom)
|
|
Map_QM.rotationAngle(Config.deviceObj.angle || 0)
|
|
Map_QM.controls.enableRotate = false
|
|
},
|
|
changeMapModel: function (model) {
|
|
if (model == '2D') {
|
|
Config.setModelState('2d')
|
|
Map_QM.camera = cameraOrtho
|
|
Map_QM.controls.maxPolarAngle = 0
|
|
Map_QM.controls.minPolarAngle = 0
|
|
Map_QM.controls.object = Map_QM.camera
|
|
} else {
|
|
Config.setModelState('3d')
|
|
Map_QM.camera = cameraPerspective
|
|
Map_QM.controls.object = Map_QM.camera
|
|
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.3
|
|
Map_QM.controls.minPolarAngle = 0.3
|
|
Map_QM.controls.reset()
|
|
let angle = Config.deviceAng ? Config.deviceObj.angle : Config.mapAngle
|
|
Map_QM.rotationAngle(angle)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api {方法} onShowLocalSite(0) 局部显示放大
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 局部显示放大 point 传入放大目标点,zoom放大级别 1-5
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {Object} point 放大的地图位置
|
|
* @apiParam {int} zoom 放大倍数
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {Object} 请求示例
|
|
*
|
|
* Map_QM.onShowLocalSite({point:{x:0,y:0},zoom:5});
|
|
*
|
|
*/
|
|
onShowLocalSite: function (obj) {
|
|
Config.setModelState('3d')
|
|
Map_QM.camera = cameraPerspective
|
|
Map_QM.controls.object = Map_QM.camera
|
|
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.3
|
|
Map_QM.controls.minPolarAngle = 0.3
|
|
Map_QM.controls.reset()
|
|
let angle = Config.deviceAng ? Config.deviceObj.angle : Config.mapAngle
|
|
Map_QM.rotationAngle(angle)
|
|
Map_QM.controls.target = new THREE.Vector3(obj.point.x * Config.sceneGap.scale, 0, obj.point.y * Config.sceneGap.scale)
|
|
let disX = 60 + (5 - parseInt(obj.zoom)) * 300
|
|
Map_QM.controls.object.position.set(obj.point.x * Config.sceneGap.scale, disX, obj.point.y * Config.sceneGap.scale + disX) // 加 disX 保持地图倾斜角度
|
|
},
|
|
|
|
/**
|
|
* @api {方法} changeLanguage() 切换中英文
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 切换中英文 cn en
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {String} str 显示语言
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.changeLanguage("en");
|
|
*
|
|
*/
|
|
changeLanguage: function (lang = 'cn') {
|
|
language = lang
|
|
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].labelObj.traverse(obj => {
|
|
if (obj.element) {
|
|
obj.element.innerText = language == 'en' ? obj.element.dataset.nameEn : obj.element.dataset.name
|
|
}
|
|
})
|
|
Map_QM.mapArr[t][i].iconLabel.traverse(obj => {
|
|
if (obj.element) {
|
|
obj.element.innerText = language == 'en' ? obj.element.dataset.nameEn : obj.element.dataset.name
|
|
}
|
|
})
|
|
}
|
|
}
|
|
Map_QM.collisionChock()
|
|
},
|
|
/**
|
|
* @api {方法} onShowDeviceSite() 地图方向复位
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 地图方向复位
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.onShowDeviceSite();
|
|
*
|
|
*/
|
|
onShowDeviceSite: function () {
|
|
Config.setModelState('3d')
|
|
Map_QM.camera = cameraPerspective
|
|
Map_QM.controls.setZoom(1)
|
|
Map_QM.controls.object = Map_QM.camera
|
|
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.3
|
|
Map_QM.controls.minPolarAngle = 0.3
|
|
if (Map_QM.qiModel) {
|
|
Map_QM.qiModel.visible = true
|
|
}
|
|
if (Map_QM.dirIcon) {
|
|
Map_QM.dirIcon.visible = false
|
|
}
|
|
Map_QM.controls.enabled = true
|
|
Map_QM.controls.enableRotate = true
|
|
Map_QM.controls.reset()
|
|
let angle = Config.deviceAng ? Config.deviceObj.angle : Config.mapAngle
|
|
Map_QM.rotationAngle(angle)
|
|
},
|
|
/**
|
|
* 在2D 状态下平移镜头
|
|
*/
|
|
moveCameraBy2D: function (obj) {
|
|
if (pathCameraState == '2D' && Map_QM.camera == cameraOrtho) {
|
|
Map_QM.controls.minAzimuthAngle = (Config.deviceObj.angle * Math.PI) / -180
|
|
Map_QM.controls.maxAzimuthAngle = (Config.deviceObj.angle * Math.PI) / -180
|
|
Map_QM.controls.object.position.set(0, 200, obj.y * Config.sceneGap.scale)
|
|
Map_QM.controls.target = new THREE.Vector3(obj.x * Config.sceneGap.scale, 0, obj.y * Config.sceneGap.scale) //移动
|
|
}
|
|
},
|
|
/**
|
|
* 方向复位
|
|
*/
|
|
resetMeDir: function () {
|
|
Config.setModelState('3d')
|
|
Map_QM.camera = cameraPerspective
|
|
Map_QM.controls.object = Map_QM.camera
|
|
Map_QM.controls.setZoom(1)
|
|
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.3
|
|
Map_QM.controls.minPolarAngle = 0.3
|
|
Map_QM.controls.minAzimuthAngle = -Infinity
|
|
Map_QM.controls.maxAzimuthAngle = Infinity
|
|
Map_QM.controls.target = new THREE.Vector3(0, 0, 0)
|
|
Map_QM.dirIcon.visible = false
|
|
Map_QM.qiIcon.visible = false
|
|
if (Map_QM.qiModel) {
|
|
Map_QM.qiModel.visible = true
|
|
}
|
|
Map_QM.controls.reset()
|
|
let angle = Config.deviceAng ? Config.deviceObj.angle : Config.mapAngle
|
|
Map_QM.rotationAngle(angle)
|
|
},
|
|
/**
|
|
* @api {方法} changePathDir(pathState) 切换导航方向
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 切换导航方向
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {String} pathState 地图导航方向 2D/3D
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.changePathDir("2D");
|
|
*
|
|
*/
|
|
changePathDir: function (pathState = '3D') {
|
|
if (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
|
|
}
|
|
if (pathCameraState == '2D') {
|
|
//2D导航
|
|
Map_QM.onShowMeDir(2)
|
|
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 {方法} cancelSelectShop() 取消店铺弹跳
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 取消店铺弹跳效果
|
|
* @apiVersion 1.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 1.0.0
|
|
*
|
|
* @apiParam {boolean} isShow 店铺促销标签是否显示
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {boolean} 请求示例
|
|
*
|
|
* Map_QM.changeStateShopPro(true);
|
|
*
|
|
*/
|
|
changeStateShopPro: function (isShow = false) {
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].tagObj.traverse(obj => {
|
|
obj.visible = isShow
|
|
})
|
|
},
|
|
/**
|
|
* @api {方法} changeShowTagObjState(isShow) 自定义标签
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 自定义标签展示/隐藏
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {boolean} isShow 自定义标签是否显示
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {boolean} 请求示例
|
|
*
|
|
* Map_QM.changeShowTagObjState(true);
|
|
*
|
|
*/
|
|
changeShowTagObjState: function (isShow = false) {
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].showTagObj.traverse(obj => {
|
|
obj.visible = isShow
|
|
})
|
|
},
|
|
|
|
/**
|
|
* @api {方法} drawCurveLine(startShop,endShop) 获取店铺列表信息
|
|
* @apiGroup 地图数据
|
|
* @apiDescription 店铺列表
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.queryShopList()
|
|
*
|
|
*/
|
|
queryShopList: function () {
|
|
return JSON.parse(JSON.stringify(Config.shopData))
|
|
},
|
|
/**
|
|
* @api {方法} drawCurveLine(startShop,endShop,color) 绘制引导线
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 绘制引导线
|
|
* @apiVersion 1.0.1
|
|
*
|
|
* @apiParam {string/Array} startShop 起始店铺编号或编号数组
|
|
* @apiParam {string/Array} endShop 终点店铺编号或编号数组
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
* //绘制一到多
|
|
* Map_QM.drawCurveLine('L125',['L117','L127','L130'],'#2246d8')
|
|
* //绘制多到一
|
|
* Map_QM.drawCurveLine(['L117','L127','L130'],'L125','#2246d8')
|
|
*
|
|
*/
|
|
drawCurveLine: function (startShop, endShop, color = '#0099ff') {
|
|
let sp, ep, cp1, cp2
|
|
if (Array.isArray(startShop) && Array.isArray(endShop)) {
|
|
return { msg: '只能有一个数组' }
|
|
}
|
|
if (Array.isArray(startShop)) {
|
|
//如果是数组
|
|
endShop = Map_QM.shopNumToNavPoint({ shopNum: endShop }, 'shop')
|
|
for (let i = 0; i < startShop.length; i++) {
|
|
startShop[i] = Map_QM.shopNumToNavPoint({ shopNum: startShop[i] }, 'shop')
|
|
sp = new THREE.Vector3(startShop[i].xaxis, -1 * startShop[i].yaxis, Config.shopHeight)
|
|
ep = new THREE.Vector3(endShop.xaxis, -1 * endShop.yaxis, Config.shopHeight)
|
|
let s = Math.sqrt(
|
|
(endShop.xaxis - startShop[i].xaxis) * (endShop.xaxis - startShop[i].xaxis) + (endShop.yaxis - startShop[i].yaxis) * (endShop.yaxis - startShop[i].yaxis)
|
|
)
|
|
cp1 = new THREE.Vector3(
|
|
startShop[i].xaxis + (endShop.xaxis - startShop[i].xaxis) / 3,
|
|
-1 * startShop[i].yaxis - (endShop.yaxis - startShop[i].yaxis) / 3,
|
|
Config.shopHeight + s / 5
|
|
)
|
|
cp2 = new THREE.Vector3(endShop.xaxis, -1 * endShop.yaxis, Config.shopHeight + s / 3)
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].lineObj.add(Config.drawDashedLine(sp, ep, s / 10, color, cp1, cp2))
|
|
}
|
|
} else {
|
|
startShop = Map_QM.shopNumToNavPoint({ shopNum: startShop }, 'shop')
|
|
if (Array.isArray(endShop)) {
|
|
//如果是数组
|
|
for (let i = 0; i < endShop.length; i++) {
|
|
endShop[i] = Map_QM.shopNumToNavPoint({ shopNum: endShop[i] }, 'shop')
|
|
sp = new THREE.Vector3(startShop.xaxis, -1 * startShop.yaxis, Config.shopHeight)
|
|
ep = new THREE.Vector3(endShop[i].xaxis, -1 * endShop[i].yaxis, Config.shopHeight)
|
|
let s = Math.sqrt(
|
|
(endShop[i].xaxis - startShop.xaxis) * (endShop[i].xaxis - startShop.xaxis) + (endShop[i].yaxis - startShop.yaxis) * (endShop[i].yaxis - startShop.yaxis)
|
|
)
|
|
cp1 = new THREE.Vector3(
|
|
startShop.xaxis + (endShop[i].xaxis - startShop.xaxis) / 3,
|
|
-1 * startShop.yaxis - (endShop[i].yaxis - startShop.yaxis) / 3,
|
|
Config.shopHeight + s / 5
|
|
)
|
|
cp2 = new THREE.Vector3(endShop[i].xaxis, -1 * endShop[i].yaxis, Config.shopHeight + s / 3)
|
|
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].lineObj.add(Config.drawDashedLine(sp, ep, s / 10, color, cp1, cp2))
|
|
}
|
|
} else {
|
|
endShop = Map_QM.shopNumToNavPoint({ shopNum: endShop }, 'shop')
|
|
sp = new THREE.Vector3(startShop.xaxis, -1 * startShop.yaxis, Config.shopHeight)
|
|
ep = new THREE.Vector3(endShop.xaxis, -1 * endShop.yaxis, Config.shopHeight)
|
|
let s = Math.sqrt((endShop.xaxis - startShop.xaxis) * (endShop.xaxis - startShop.xaxis) + (endShop.yaxis - startShop.yaxis) * (endShop.yaxis - startShop.yaxis))
|
|
cp1 = new THREE.Vector3(
|
|
startShop.xaxis + (endShop.xaxis - startShop.xaxis) / 3,
|
|
-1 * startShop.yaxis - (endShop.yaxis - startShop.yaxis) / 3,
|
|
Config.shopHeight + s / 5
|
|
)
|
|
cp2 = new THREE.Vector3(endShop.xaxis, -1 * endShop.yaxis, Config.shopHeight + s / 3)
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].lineObj.add(Config.drawDashedLine(sp, ep, s / 10, color, cp1, cp2))
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} drawColumnar(source,property) 绘制柱状图
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 绘制柱状图
|
|
* @apiVersion 1.0.1
|
|
*
|
|
* @apiParam source 起始店铺编号或编号数组
|
|
* @apiParam property 控制参数对象
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
* //绘制多个
|
|
* Map_QM.drawColumnar(['L117','L127','L130'],{'height':200,'width':20,'color':'#2246d8'})
|
|
* //绘制单个
|
|
* Map_QM.drawColumnar('L125',{'height':200,'width':20,'color':'#2246d8'})
|
|
*/
|
|
drawColumnar: function (source, property) {
|
|
if (Array.isArray(source)) {
|
|
if (source.length == 0) {
|
|
return { msg: '不能解析空数组' }
|
|
}
|
|
for (let i = 0; i < source.length; i++) {
|
|
Map_QM.drawOnlyColumer(source[i], property)
|
|
}
|
|
} else {
|
|
Map_QM.drawOnlyColumer(source, property)
|
|
}
|
|
},
|
|
drawOnlyColumer: function (shopNum, property) {
|
|
if (shopNum.trim() != '' && property) {
|
|
endShop = Map_QM.shopNumToNavPoint({ shopNum: shopNum }, 'shop')
|
|
let geometry = new THREE.BoxGeometry(property.width * 2, property.width * 2, property.width * 2)
|
|
let c = new THREE.Color(property.color)
|
|
let material = new THREE.ShaderMaterial({
|
|
uniforms: {
|
|
targetColor: { value: new THREE.Vector3(c.r, c.g, c.b) },
|
|
height: { value: property.height / 5 }
|
|
},
|
|
transparent: true,
|
|
opacity: property.opacity,
|
|
//depthTest:false,
|
|
vertexShader: [
|
|
'varying vec3 modelPos;',
|
|
'void main() {',
|
|
' modelPos = position;',
|
|
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
|
|
'}'
|
|
].join('\n'),
|
|
fragmentShader: [
|
|
'uniform vec3 targetColor;',
|
|
'uniform float height;',
|
|
'varying vec3 modelPos;',
|
|
'void main() {',
|
|
' gl_FragColor = vec4(targetColor.xyz,(1.0 - modelPos.y/height)*(1.0 - modelPos.y/height));',
|
|
'}'
|
|
].join('\n')
|
|
})
|
|
//let material = new THREE.MeshPhongMaterial( { color: property.color, opacity: property.opacity, transparent:true, side: THREE.DoubleSide } );
|
|
let mesh = new THREE.Mesh(geometry, material)
|
|
mesh.position.set(endShop.xaxis, -1 * endShop.yaxis, property.height)
|
|
mesh.rotation.x = Math.PI / -2
|
|
mesh.scale.setY(property.height / property.width)
|
|
let material_line
|
|
for (let k = 0; k < Config.lineBasicMaterialArr.length; k++) {
|
|
let color2 = new THREE.Color(property.color)
|
|
if (Config.lineBasicMaterialArr[k].color.equals(color2)) {
|
|
material_line = Config.lineBasicMaterialArr[k]
|
|
}
|
|
}
|
|
if (!material_line) {
|
|
material_line = new THREE.LineBasicMaterial({
|
|
color: property.color
|
|
}) //材质对象lineColor
|
|
Config.lineBasicMaterialArr.push(material_line)
|
|
}
|
|
let cubeEdges = new THREE.EdgesGeometry(geometry, 60)
|
|
mesh.add(new THREE.LineSegments(cubeEdges, material))
|
|
mesh.userData.type = 'columer'
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].lineObj.add(mesh)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api {方法} removeDrawEle(type) 删除绘制元素
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 删除绘制元素
|
|
* @apiVersion 1.0.1
|
|
*
|
|
* @apiParam type 传入删除的类型 toLine--引导线 columer--柱状样式 all---所有
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.removeDrawEle('toLine')
|
|
*
|
|
*/
|
|
removeDrawEle: function (type) {
|
|
let lineObj = Map_QM.mapArr[Config.selectBuild][Config.selectFloor].lineObj
|
|
for (let j = lineObj.children.length - 1; j >= 0; j--) {
|
|
console.log(lineObj.children[j].userData)
|
|
if (type == 'all' || lineObj.children[j].userData.type == type) {
|
|
lineObj.remove(lineObj.children[j])
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} rotationAngle(angle) 改变水平角度
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 改变地图水平角度 angle>-180 && angle<180
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {int} angle 旋转角度
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {int} 请求示例
|
|
*
|
|
* Map_QM.rotationAngle(90);
|
|
*
|
|
*/
|
|
rotationAngle: function (angle) {
|
|
Map_QM.controls.setRotateHorizontal((angle / 180) * Math.PI)
|
|
},
|
|
|
|
/**
|
|
* @api {方法} setCameraDist(cDist) 调整地图大小
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 调整地图大小(值越小地图越大) Config.mapDistance.min ~ Config.mapDistance.max
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {int} cDist 摄像头距离
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {int} 请求示例
|
|
*
|
|
* Map_QM.setCameraDist(150);
|
|
*
|
|
*/
|
|
setCameraDist: function (cDist) {
|
|
clearTimeout(oTime)
|
|
oTime = setTimeout(() => {
|
|
clearTimeout(oTime)
|
|
if (Config.mapDistance.min < parseInt(cDist) && parseInt(cDist) < Config.mapDistance.max) {
|
|
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.collisionChock()
|
|
}
|
|
})
|
|
}
|
|
}, 200)
|
|
},
|
|
/**
|
|
* @api {方法} startRender() 启动地图渲染
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 启动地图渲染 与 cancelRender 配合使用可节约资源
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiSampleRequest off
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.startRender();
|
|
*
|
|
*/
|
|
startRender: function () {
|
|
Map_QM.cancelRender()
|
|
renderFrame = requestAnimationFrame(Map_QM.startRender)
|
|
let T = clock.getDelta()
|
|
timeS = timeS + T
|
|
// requestAnimationFrame默认调用render函数60次,通过时间判断,降低renderer.render执行频率
|
|
if (timeS > 0.03) {
|
|
if (Map_QM.qiModel) {
|
|
Map_QM.qiModel.rotateY(0.05)
|
|
}
|
|
if (Map_QM.endModel) {
|
|
Map_QM.endModel.rotateY(0.05)
|
|
}
|
|
Map_QM.controls.update()
|
|
Map_QM.renderer.render(Map_QM.scene, Map_QM.camera)
|
|
Map_QM.labelRenderer.render(Map_QM.scene, Map_QM.camera)
|
|
for (let item of Map_QM.mixers) {
|
|
item.update(T)
|
|
}
|
|
//timeS置0
|
|
timeS = 0
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} cancelRender() 取消地图渲染
|
|
* @apiGroup 地图显示
|
|
* @apiDescription 取消地图渲染 与 startRender 配合使用可节约资源
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.cancelRender();
|
|
*
|
|
*/
|
|
cancelRender: function () {
|
|
window.cancelAnimationFrame(renderFrame)
|
|
renderFrame = -1
|
|
},
|
|
|
|
/**
|
|
* @api {方法} showFloor(floorOrder) 楼层切换
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 楼层切换,传入楼层编号,编号从下到上排序,最下面是0
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {int} floorOrder 楼层编号
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {int} 请求示例
|
|
*
|
|
* Map_QM.showFloor(1);
|
|
*
|
|
*/
|
|
showFloor: function (fIndex = -1) {
|
|
isPathState = false
|
|
if (Map_QM.qiIcon) {
|
|
Map_QM.qiIcon.visible = false
|
|
}
|
|
Map_QM.controls.enabled = true
|
|
Map_QM.controls.enableRotate = true
|
|
Map_QM.controls.setZoom(1)
|
|
Map_QM.controls.minAzimuthAngle = -Infinity
|
|
Map_QM.controls.maxAzimuthAngle = Infinity
|
|
Map_QM.dispatchEvent({
|
|
type: 'changeFloorinit',
|
|
data: Map_QM.selectFloor
|
|
})
|
|
Map_QM.clearFloor(fIndex)
|
|
if (Config.cameraDist.state == '3D') {
|
|
Map_QM.resetMeDir()
|
|
} else {
|
|
if (Map_QM.dirIcon) {
|
|
Map_QM.dirIcon.visible = true
|
|
}
|
|
}
|
|
clearTimeout(outTime)
|
|
Map_QM.forShopArr.length = 0
|
|
forShopArr = { direction: '', wayList: [] }
|
|
if (fIndex != -1) {
|
|
Map_QM.changeFloorInner(fIndex)
|
|
}
|
|
Map_QM.controls.reset()
|
|
if (Config.showlap) {
|
|
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.3
|
|
Map_QM.controls.minPolarAngle = 1.2
|
|
} else {
|
|
Map_QM.controls.maxPolarAngle = Math.PI / 2 - 0.3
|
|
Map_QM.controls.minPolarAngle = 0.3
|
|
}
|
|
// let angle = Config.deviceAng?Config.deviceObj.angle : Config.mapAngle;
|
|
// Map_QM.rotationAngle(angle);
|
|
},
|
|
|
|
/**
|
|
* @api {方法} addElementLabel(divObj,x=0,y=0,type="2d_pop") 地图html标签
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 地图显示Html标签
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {Element} divObj div对象
|
|
* @apiParam {int} x 显示X坐标
|
|
* @apiParam {int} y 显示Y坐标
|
|
* @apiParam {string} type 对象标识
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
* Map_QM.addElementLabel(divObj,0,0,"shopInfo");
|
|
*
|
|
*/
|
|
addElementLabel: function (divObj, x = 0, y = 0, type = 'shopInfo') {
|
|
Map_QM.elementDestroy(type)
|
|
let shopInfo = new THREE.CSS2DObject(divObj)
|
|
shopInfo.position.set(x, -1 * y, type === 'shopInfo' ? (Config.shopHeight || 50) + 100 : 150)
|
|
shopInfo.applyMatrix(Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.matrix)
|
|
shopInfo.userData.type = type
|
|
shopInfo.name = 'shopInfo'
|
|
Map_QM.CSSObject.add(shopInfo)
|
|
return shopInfo
|
|
},
|
|
/**
|
|
* @api {方法} updateElementPosition(3DObj,x=0,y=0) 修改标签位置
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 修改标签位置
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {Object} obj 对象
|
|
* @apiParam {int} x 新的X坐标
|
|
* @apiParam {int} y 新的Y坐标
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.updateElementPosition("2d_pop");
|
|
*
|
|
*/
|
|
updateElementPosition: function (obj, x, y) {
|
|
if (obj.hasOwnProperty('position')) {
|
|
let h = Config.shopHeight || 50
|
|
obj.position.set(x, -1 * y, h)
|
|
obj.applyMatrix(Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.matrix)
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} elementDestroy(divObj,x=0,y=0,type="2d_pop") 销毁地图标签
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 销毁地图上的html标签
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {string} type 对象标识
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.elementDestroy("2d_pop");
|
|
*
|
|
*/
|
|
elementDestroy: function (type = '2d_pop') {
|
|
for (let i = Map_QM.CSSObject.children.length - 1; i >= 0; i--) {
|
|
if (Map_QM.CSSObject.children[i].userData && Map_QM.CSSObject.children[i].userData.type == type) {
|
|
Map_QM.CSSObject.remove(Map_QM.CSSObject.children[i])
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} initSingleDevice(floorOrder,code) 设置标签背景色
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 设置标签背景色
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} floorOrder 标签所在楼层
|
|
* @apiParam {string} code 对象标识
|
|
* @apiParam {string} color 选中颜色 (可选)
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.initSingleDevice(0,"");
|
|
*/
|
|
initSingleDevice: function (floorOrder, code, color = '#5F4E41', build = 0) {
|
|
Map_QM.mapArr[build][floorOrder].showTagObj.traverse(obj => {
|
|
if (obj.element && obj.userData.code == code) {
|
|
obj.element.style.background = color
|
|
}
|
|
})
|
|
},
|
|
/**
|
|
* @api {方法} clearDeviceSelectState() 清除标签选中
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 清除标签选中状态
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} floorOrder 标签所在楼层
|
|
* @apiParam {string} code 对象标识
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.clearDeviceSelectState();
|
|
*/
|
|
clearDeviceSelectState: function () {
|
|
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].showTagObj.traverse(obj => {
|
|
if (obj.element) {
|
|
obj.element.style.background = '#777777'
|
|
}
|
|
})
|
|
}
|
|
}
|
|
},
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* 内部楼层切换
|
|
* @param {int} fIndex 楼层编号
|
|
* @param {int} midIndex 如果是叠层,需要传入 最多三层
|
|
* @param {int} endIndex 如果是叠层,需要传入 最多三层
|
|
*/
|
|
changeFloorInner: function (fIndex = -1, endIndex = -1, midIndex = -1) {
|
|
Map_QM.clearFloor(Config.selectFloor)
|
|
pathShop = ''
|
|
let addFloor = fIndex - Config.selectFloor > 0 ? 1 : -1
|
|
if (fIndex != -1) {
|
|
Config.selectFloor = fIndex
|
|
}
|
|
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 == Config.selectBuild ? true : false
|
|
Map_QM.mapArr[t][i].labelObj.traverse(obj => {
|
|
obj.visible = false
|
|
})
|
|
Map_QM.mapArr[t][i].iconLabel.traverse(obj => {
|
|
obj.visible = false
|
|
})
|
|
|
|
Map_QM.mapArr[t][i].tagObj.traverse(obj => {
|
|
obj.visible = false
|
|
})
|
|
Map_QM.mapArr[t][i].showTagObj.traverse(obj => {
|
|
obj.visible = false
|
|
})
|
|
}
|
|
}
|
|
if (Map_QM.mapArr[Config.selectBuild][Config.selectFloor]) {
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.visible = true
|
|
} else {
|
|
return
|
|
}
|
|
|
|
for (let i = 0; i < Map_QM.mapArr[Config.selectBuild].length; i++) {
|
|
if (Config.showlap) {
|
|
let moveZ = (i - Config.selectFloor) * Config.doubleDist
|
|
Map_QM.mapArr[Config.selectBuild][i].labelObj.traverse(obj => {
|
|
obj.visible = false
|
|
})
|
|
Map_QM.mapArr[Config.selectBuild][i].iconLabel.traverse(obj => {
|
|
obj.visible = false
|
|
})
|
|
Map_QM.mapArr[Config.selectBuild][i].showTagObj.traverse(obj => {
|
|
obj.visible = false
|
|
})
|
|
TweenMax.to(Map_QM.mapArr[Config.selectBuild][i].allObj.position, 0.3, {
|
|
y: moveZ,
|
|
onComplete: function () {
|
|
Map_QM.mapArr[Config.selectBuild][i].allObj.visible = true
|
|
Map_QM.mapArr[Config.selectBuild][i].iconLabel.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
Map_QM.mapArr[Config.selectBuild][i].showTagObj.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
if (i == Config.selectFloor) {
|
|
Map_QM.mapArr[Config.selectBuild][i].labelObj.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
if (i == Config.selectFloor || (i == midIndex && Config.overlap) || (i == endIndex && Config.overlap)) {
|
|
Map_QM.mapArr[Config.selectBuild][i].allObj.visible = true
|
|
Map_QM.mapArr[Config.selectBuild][i].labelObj.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
Map_QM.mapArr[Config.selectBuild][i].iconLabel.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
|
|
Map_QM.mapArr[Config.selectBuild][i].showTagObj.traverse(obj => {
|
|
obj.visible = true
|
|
})
|
|
} else {
|
|
Map_QM.mapArr[Config.selectBuild][i].allObj.visible = false
|
|
}
|
|
if (i == Map_QM.mapArr[Config.selectBuild].length - 1 && !Config.showlap) {
|
|
if (Config.overlap) {
|
|
//叠层
|
|
if (midIndex === -1 && endIndex !== -1) {
|
|
//两层
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.position.y = Config.selectFloor < endIndex ? -1 * Config.doubleDist : Config.doubleDist
|
|
Map_QM.mapArr[Config.selectBuild][endIndex].allObj.position.y = Config.selectFloor > endIndex ? -1 * Config.doubleDist : Config.doubleDist
|
|
} else if (endIndex === -1) {
|
|
//一层
|
|
TweenMax.fromTo(
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.position,
|
|
0.5,
|
|
{ y: addFloor * Config.doubleDist },
|
|
{ y: 0, ease: Cubic.easeIn }
|
|
)
|
|
//Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.position.y=0;
|
|
} else {
|
|
//三层
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.position.y = 0
|
|
Map_QM.mapArr[Config.selectBuild][midIndex].allObj.position.y = 0
|
|
Map_QM.mapArr[Config.selectBuild][endIndex].allObj.position.y = 0
|
|
let minF = Math.min(midIndex, Config.selectFloor, endIndex)
|
|
let maxF = Math.max(midIndex, Config.selectFloor, endIndex)
|
|
Map_QM.mapArr[Config.selectBuild][minF].allObj.position.y = -1 * Config.doubleDist
|
|
Map_QM.mapArr[Config.selectBuild][maxF].allObj.position.y = Config.doubleDist
|
|
}
|
|
} else {
|
|
//Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.position.y=0;
|
|
TweenMax.fromTo(Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.position, 0.5, { y: addFloor * Config.doubleDist }, { y: 0, ease: Cubic.easeIn })
|
|
}
|
|
Map_QM.timeOutInit()
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @param {Object} e
|
|
* 地图BOX点击
|
|
*/
|
|
onMouseClickBox: function (event) {
|
|
clearTimeout(oTime)
|
|
oTime = setTimeout(() => {
|
|
clearTimeout(oTime)
|
|
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)
|
|
}, 200)
|
|
},
|
|
onCallTouchORMouse: function (mouse) {
|
|
if (!Map_QM.mapArr[Config.selectBuild][Config.selectFloor] || isPathState) {
|
|
return
|
|
}
|
|
let raycaster = new THREE.Raycaster()
|
|
raycaster.setFromCamera(mouse, Map_QM.camera)
|
|
let intersects = raycaster.intersectObjects(Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.children, true)
|
|
let clickShop = false
|
|
for (let i = 0; i < intersects.length; i++) {
|
|
//店铺BOX点击
|
|
if (intersects[i].object.userData && intersects[i].object.userData.type == 'shop' && intersects[i].object.name != 'shop' && intersects[i].object.name != '') {
|
|
if (Map_QM.endModel && Map_QM.endModel.visible) {
|
|
Map_QM.endModel.visible = false
|
|
}
|
|
clickShop = true
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].findPath.clearPath()
|
|
Map_QM.setSelectShopMat(intersects[i].object)
|
|
break
|
|
}
|
|
}
|
|
Map_QM.dispatchEvent({
|
|
type: 'shop',
|
|
data: clickShop ? Map_QM.selectShop?.userData : null
|
|
})
|
|
//图标点击
|
|
for (let i = 0; i < intersects.length; i++) {
|
|
//图标点击
|
|
if (intersects[i].object.userData && intersects[i].object.userData.type == 'icon') {
|
|
if (Map_QM.endModel && Map_QM.endModel.visible) {
|
|
Map_QM.endModel.visible = false
|
|
}
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].findPath.clearPath()
|
|
Map_QM.dispatchEvent({
|
|
type: 'icon',
|
|
data: intersects[i].object.userData
|
|
})
|
|
break
|
|
}
|
|
}
|
|
//设备点击
|
|
for (let i = 0; i < intersects.length; i++) {
|
|
//图标点击
|
|
if (intersects[i].object.userData && intersects[i].object.userData.type == 'device') {
|
|
if (Map_QM.endModel && Map_QM.endModel.visible) {
|
|
Map_QM.endModel.visible = false
|
|
}
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].findPath.clearPath()
|
|
Map_QM.dispatchEvent({
|
|
type: 'device',
|
|
data: intersects[i].object.userData
|
|
})
|
|
break
|
|
}
|
|
}
|
|
},
|
|
//改变选中店铺box
|
|
setSelectShopMat: function (selObject, logoW = 0, url = '') {
|
|
TweenMax.killAll(true)
|
|
if (Map_QM.selectShop) {
|
|
Map_QM.selectShop.scale.z = 1
|
|
}
|
|
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 })
|
|
}
|
|
}
|
|
})
|
|
},
|
|
/**
|
|
* 初始化后调用
|
|
*/
|
|
timeOutInit: function () {
|
|
if (Map_QM.callBackLoadOver) {
|
|
let floorData = []
|
|
for (let i = 0; i < Config.allMap.length; i++) {
|
|
let build = []
|
|
for (let j = 0; j < Config.allMap[i].buildArr.length; j++) {
|
|
if (Config.allMap[i].buildArr[j]) {
|
|
build.push({ order: Config.allMap[i].buildArr[j].order, name: Config.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
|
|
})
|
|
Map_QM.collisionChock()
|
|
},
|
|
/**
|
|
* 碰撞检测
|
|
* @param {Object} 传入检测楼层下标
|
|
*/
|
|
collisionChock: function () {
|
|
if (!Config.collision) {
|
|
return
|
|
}
|
|
Map_QM.dispatchEvent({
|
|
type: 'mapAngleChange',
|
|
data: { hAngle: Map_QM.controls.getRotateHorizontal(), vAngle: Map_QM.controls.getRotate() }
|
|
})
|
|
outTime = setTimeout(() => {
|
|
clearTimeout(outTime)
|
|
let checkList = []
|
|
if (Config.overlap) {
|
|
for (let i = 0; i < Map_QM.mapArr[Config.selectBuild].length; i++) {
|
|
Map_QM.mapArr[Config.selectBuild][i].allObj.traverse(obj => {
|
|
if (obj.name == 'floor' && Map_QM.mapArr[Config.selectBuild][i].allObj.visible) {
|
|
//
|
|
checkList.push(obj)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
if (Config.showlap) {
|
|
//叠层展示
|
|
for (let i = 0; i < Map_QM.mapArr[Config.selectBuild].length; i++) {
|
|
Map_QM.mapArr[Config.selectBuild][i].allObj.traverse(obj => {
|
|
if (obj.name == 'floor' && Map_QM.mapArr[Config.selectBuild][i].allObj.visible && i > Config.selectFloor) {
|
|
//
|
|
checkList.push(obj)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
if (Map_QM.mapArr[Config.selectBuild]) {
|
|
for (let m = 0; m < Map_QM.mapArr[Config.selectBuild].length; m++) {
|
|
if (Map_QM.mapArr[Config.selectBuild][m].allObj.visible) {
|
|
let IconChilds = Map_QM.mapArr[Config.selectBuild][m].iconLabel.children
|
|
IconChilds.forEach(item => {
|
|
item.element.style.visibility = 'visible'
|
|
})
|
|
let childs = Map_QM.mapArr[Config.selectBuild][m].labelObj.children
|
|
childs.forEach(item => {
|
|
item.element.style.visibility = 'visible'
|
|
})
|
|
let svgChilds = Map_QM.mapArr[Config.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 len = childs.length
|
|
for (let i = 0; i < len; i++) {
|
|
let obj = childs[i].element
|
|
if (obj.style.visibility == 'visible' && obj.style.transform) {
|
|
let labP = obj.style.transform.split('translate')[2].split(', ')
|
|
for (let j = i + 1; j < len; j++) {
|
|
let pb = childs[j].element.style.transform.split('translate')[2].split(', ')
|
|
let isCol = Config.isCollision(
|
|
new Config.Point(labP[0].substring(1, labP[0].length - 2), labP[1].substring(0, labP[1].length - 3)),
|
|
obj.clientWidth,
|
|
obj.clientHeight,
|
|
new Config.Point(pb[0].substring(1, pb[0].length - 2), pb[1].substring(0, pb[1].length - 3)),
|
|
childs[j].element.clientWidth,
|
|
childs[j].element.clientHeight
|
|
)
|
|
if (isCol) {
|
|
childs[j].element.style.visibility = 'hidden'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let iLen = IconChilds.length
|
|
for (let ii = 0; ii < iLen; ii++) {
|
|
let objIcon = IconChilds[ii].element
|
|
if (objIcon.style.visibility == 'visible' && objIcon.style.transform) {
|
|
let labPIcon = objIcon.style.transform.split('translate')[2].split(', ')
|
|
for (let jj = ii + 1; jj < iLen; jj++) {
|
|
let pbe = IconChilds[jj].element.style.transform.split('translate')[2].split(', ')
|
|
let isCol2 = Config.isCollision(
|
|
new Config.Point(labPIcon[0].substring(1, labPIcon[0].length - 2), labPIcon[1].substring(0, labPIcon[1].length - 3)),
|
|
objIcon.clientWidth,
|
|
objIcon.clientHeight,
|
|
new Config.Point(pbe[0].substring(1, pbe[0].length - 2), pbe[1].substring(0, pbe[1].length - 3)),
|
|
IconChilds[jj].element.clientWidth,
|
|
IconChilds[jj].element.clientHeight
|
|
)
|
|
if (isCol2) {
|
|
IconChilds[jj].element.style.visibility = 'hidden'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (Config.overlap || Config.showlap) {
|
|
let renChild = Map_QM.mapArr[Config.selectBuild][m].showTagObj.children
|
|
renChild.forEach(item => {
|
|
if (item.element.style.visibility == 'visible') {
|
|
let check = Config.blocked(item.element, checkList, m)
|
|
if (check) {
|
|
item.element.style.visibility = 'hidden'
|
|
}
|
|
}
|
|
})
|
|
childs.forEach(item => {
|
|
if (item.element.style.visibility == 'visible') {
|
|
let check = Config.blocked(item.element, checkList, m)
|
|
if (check) {
|
|
item.element.style.visibility = 'hidden'
|
|
}
|
|
}
|
|
})
|
|
IconChilds.forEach(item => {
|
|
if (item.element.style.visibility == 'visible') {
|
|
let check = Config.blocked(item.element, checkList, m)
|
|
if (check) {
|
|
item.element.style.visibility = 'hidden'
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}, 100)
|
|
},
|
|
|
|
/**
|
|
* 寻路----------------------------------------------------------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
/**
|
|
* @api {方法} bounceIcon({type:"xsj"}) 图标弹跳
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 地图图标弹跳效果
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {String} iconType 设施缩写
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.bounceIcon({type:"xsj"});
|
|
*
|
|
*/
|
|
bounceIcon: function (iconType) {
|
|
let toFloor = parseInt(Config.selectFloor)
|
|
let facs = Map_QM.mapArr[Config.selectBuild][toFloor].serObj.children //交通图标
|
|
for (let i = 0; i < facs.length; i++) {
|
|
if (facs[i].type == 'Sprite') {
|
|
facs[i].reSetSite()
|
|
if (facs[i].facCode == iconType) {
|
|
facs[i].jumpIcon()
|
|
}
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} pathIcon({type:"xsj"}) 获取最近设施
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 获取离当前楼层最近的设施
|
|
* @apiVersion 1.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
|
|
toIcon = iconType.type
|
|
for (let i = 0; i < Map_QM.mapArr[parseInt(Config.deviceObj.build)].length; i++) {
|
|
let sers = Map_QM.mapArr[parseInt(Config.deviceObj.build)][i].serObj.children //服务图标
|
|
for (let n = 0; n < sers.length; n++) {
|
|
if (sers[n].facCode == iconType.type) {
|
|
if (!selIcon) {
|
|
selIcon = sers[n]
|
|
minS =
|
|
Math.abs(sers[n].position.x - Config.deviceObj.xaxis) +
|
|
Math.abs(-1 * Config.deviceObj.yaxis - sers[n].position.y) +
|
|
Math.abs(i - Config.deviceObj.floor) * 3000
|
|
} else {
|
|
let s1 =
|
|
Math.abs(sers[n].position.x - Config.deviceObj.xaxis) +
|
|
Math.abs(-1 * Config.deviceObj.yaxis - sers[n].position.y) +
|
|
Math.abs(i - Config.deviceObj.floor) * 3000
|
|
if (s1 < minS) {
|
|
minS = s1
|
|
selIcon = sers[n]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (selIcon) {
|
|
return {
|
|
build: selIcon.build,
|
|
floor: selIcon.floor,
|
|
node: selIcon.navCode,
|
|
site: { x: selIcon.position.x, y: -selIcon.position.y },
|
|
typeCode: Config.getFacType(iconType.type)
|
|
}
|
|
} else {
|
|
// 当前楼栋没有
|
|
let startNade = Config.deviceObj.build + '_' + Config.startObj.floor + '_' + Config.startObj.node
|
|
for (let b = 0; b < Map_QM.mapArr.length; b++) {
|
|
if (b != parseInt(Config.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].facCode == iconType.type) {
|
|
let toNade = sers[n].build + '_' + sers[n].floor + '_' + sers[n].navCode
|
|
if (!selIcon) {
|
|
selIcon = sers[n]
|
|
let path = dijkstra.find_path(ftPath, startNade, toNade)
|
|
minS = path.cost
|
|
} else {
|
|
let path = dijkstra.find_path(ftPath, startNade, toNade)
|
|
let s1 = path.cost
|
|
if (s1 < minS) {
|
|
minS = s1
|
|
selIcon = sers[n]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (selIcon) {
|
|
return {
|
|
build: selIcon.build,
|
|
floor: selIcon.floor,
|
|
node: selIcon.navCode,
|
|
site: { x: selIcon.position.x, y: -selIcon.position.y },
|
|
typeCode: Config.getFacType(iconType.type)
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} pathByStartAndOver(startObj,toObj,callBackFun) 设置地图点位
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 根据传入的起、终点;直接导航
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} floor 楼层编号
|
|
* @apiParam {String} shopNum 店铺编号/车位编号
|
|
* @apiParam {String} type "shop"/"park"
|
|
* @apiParam {Function} callBackFun 回调函数
|
|
*
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.pathByStartAndOver({"floor":3,"shopNum":"L102","type":"shop"},{"floor":4,"shopNum":"L204","type":"shop"});
|
|
*
|
|
*/
|
|
pathByStartAndOver: function (startObj, toObj, callBackFun) {
|
|
try {
|
|
Config.startObj = this.shopNumToNavPoint(startObj, startObj.type)
|
|
let overObj = this.shopNumToNavPoint(toObj, toObj.type)
|
|
this.pathNode(overObj, callBackFun)
|
|
} catch (e) {
|
|
return '传入点位无法导航'
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api {方法} changeStartPoint({type:"xsj"}) 设置起始点位
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 设置起始点位
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} floor 起点楼层编号
|
|
* @apiParam {String} shopNum 起点店铺编号
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample {String} 请求示例
|
|
*
|
|
* Map_QM.changeStartPoint({"floor":3,"shopNum":"6220"});
|
|
*
|
|
*/
|
|
changeStartPoint: function (toObj) {
|
|
if (toObj) {
|
|
Map_QM.clearFloor()
|
|
Config.startObj = this.shopNumToNavPoint(toObj, 'shop')
|
|
} else {
|
|
Map_QM.clearFloor()
|
|
let pathData = Config.allMap[parseInt(Config.deviceObj.build)].buildArr[parseInt(Config.deviceObj.floor)].mapData.path
|
|
Config.deviceObj.xaxis = pathData.nodes[parseInt(Config.deviceObj.node)].x
|
|
Config.deviceObj.yaxis = pathData.nodes[parseInt(Config.deviceObj.node)].y
|
|
Config.startObj = Config.deviceObj
|
|
}
|
|
//Config.selectBuild = 0;
|
|
},
|
|
|
|
/**
|
|
* @api {方法} changeMapIPState(ipName,color) 改变POI颜色
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 改变POI 颜色
|
|
* @apiVersion 1.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 < Map_QM.mapArr[Config.selectBuild].length; i++) {
|
|
let shopArr = Map_QM.mapArr[Config.selectBuild][i].allObj.children
|
|
for (let k = 0; k < shopArr.length; k++) {
|
|
if (shopArr[k].name == ipName) {
|
|
shopArr[k].material = Config.getMeshMaterial(color || 0xeab16e)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
},
|
|
setSelectShopMatByName: function (ipName) {
|
|
// #775544 #AD8164
|
|
for (let i = 0; i < Map_QM.mapArr[Config.selectBuild].length; i++) {
|
|
let shopArr = Map_QM.mapArr[Config.selectBuild][i].allObj.children
|
|
for (let k = 0; k < shopArr.length; k++) {
|
|
if (shopArr[k].name == ipName) {
|
|
Map_QM.setSelectShopMat(shopArr[k])
|
|
break
|
|
}
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} getMapIPData(ipName) 获取POI 基础数据
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 获取POI 基础数据
|
|
* @apiVersion 1.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[Config.selectBuild].length; i++) {
|
|
let shopArr = Map_QM.mapArr[Config.selectBuild][i].allObj.children
|
|
for (let k = 0; k < shopArr.length; k++) {
|
|
if (shopArr[k].name == ipName) {
|
|
return shopArr[k].userData
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api {方法} pathNode() 地图模拟导航
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 地图路径模拟导航
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} floor 楼层编号
|
|
* @apiParam {string} node 路径点位编号
|
|
* @apiParam {function} callBackFun 回调方法
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.pathNode({floor:2,node:"53"},callBackFun);
|
|
*
|
|
*/
|
|
pathNode: function (toObj, callBackFun) {
|
|
Map_QM.clearFloor(-1, true)
|
|
Map_QM.selectShop = null
|
|
|
|
pathShop = ''
|
|
isPathState = true
|
|
if (!Config.startObj.xaxis && !Config.startObj.yaxis) {
|
|
Map_QM.changeStartPoint(null)
|
|
}
|
|
outTime = setTimeout(() => {
|
|
clearTimeout(outTime)
|
|
Config.overObj = null
|
|
Config.overObj = { floor: toObj.floor, node: toObj.node, shopNum: toObj.shopNum }
|
|
if (Config.overObj.node != '') {
|
|
Map_QM.cancelRender()
|
|
this.onFindPathModel()
|
|
if (Config.overlap) {
|
|
//叠层导航--固定地图仰角
|
|
Map_QM.controls.maxPolarAngle = 1.17
|
|
Map_QM.controls.minPolarAngle = 1.17
|
|
}
|
|
if (callBackFun) {
|
|
Map_QM.parseForShopArr()
|
|
const data = JSON.parse(JSON.stringify(forShopArr))
|
|
callBackFun(data)
|
|
}
|
|
Map_QM.startRender()
|
|
}
|
|
}, 200)
|
|
},
|
|
parseForShopArr: function () {
|
|
forShopArr = { direction: '', wayList: [] }
|
|
Map_QM.forShopArr.forEach((item, index) => {
|
|
if (item.hasOwnProperty('Direction')) {
|
|
forShopArr.direction = item.Direction
|
|
}
|
|
if (item.hasOwnProperty('wayShop')) {
|
|
for (let i = 0; i < item.wayShop.length; i++) {
|
|
let enTlite = item.wayShop[i].shop.shopNameEn == '' ? item.wayShop[i].shop.shopName : item.wayShop[i].shop.shopNameEn
|
|
forShopArr.wayList.push({
|
|
isFacility: false,
|
|
shopName: '经过 ' + item.wayShop[i].shop.shopName,
|
|
shopNameEn: 'PASS ' + enTlite,
|
|
logoUrl: item.wayShop[i].shop.logoUrl,
|
|
shopId: item.wayShop[i].shop.shopId
|
|
})
|
|
}
|
|
}
|
|
if (item.hasOwnProperty('Facilities')) {
|
|
//设施
|
|
forShopArr.wayList.push({
|
|
isFacility: true,
|
|
shopName: '乘坐 ' + item.Facilities.userData.title + '到 ' + Map_QM.mapArr[Config.selectBuild][parseInt(Map_QM.forShopArr[index + 1].floor)].floorName,
|
|
shopNameEn: 'BY ' + item.Facilities.userData.title + 'TO ' + Map_QM.mapArr[Config.selectBuild][parseInt(Map_QM.forShopArr[index + 1].floor)].floorName,
|
|
logoUrl: item.Facilities.imgUrl,
|
|
shopId: ''
|
|
})
|
|
}
|
|
})
|
|
},
|
|
/**
|
|
* @api {方法} getGapByPathNode() 获取实际距离
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 通过点位获取距离
|
|
* @apiVersion 1.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 = Config.selectBuild + '_' + Config.deviceObj.floor + '_' + Config.deviceObj.node
|
|
let toNade = Config.selectBuild + '_' + toObj.floor + '_' + toObj.node
|
|
let path = { cost: -1 },
|
|
minTime = 1
|
|
try {
|
|
path = dijkstra.find_path(graphPath, startNade, toNade)
|
|
minTime = parseInt(path.cost / Config.mapScale / 50) < 0.5 ? 0.5 : parseInt(path.cost / Config.mapScale / 50)
|
|
} catch (e) {
|
|
console.log(e)
|
|
}
|
|
return { dis: parseInt(path.cost / Config.mapScale), time: minTime }
|
|
},
|
|
/**
|
|
* @api {方法} getAllIcon() 获取所有Icon
|
|
* @apiGroup 地图数据
|
|
* @apiDescription 获取所有Icon
|
|
* @apiVersion 1.0.0
|
|
* @apiParam {int} floorOrder 楼层编号(可选) 不传返回所有
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
*/
|
|
getAllIcon: function (floorOrder = -1, buildOrder = -1) {
|
|
let icons = []
|
|
if (floorOrder != -1) {
|
|
let sers = Map_QM.mapArr[Config.selectBuild][floorOrder].serObj.children //服务图标
|
|
for (let n = 0; n < sers.length; n++) {
|
|
if (sers[n].type == 'Sprite') {
|
|
let title = sers[n].userData.title
|
|
let titleEn = Config.iconEn[title]
|
|
let type = sers[n].facCode
|
|
let imgUrl = sers[n].imgUrl
|
|
if (sers[n].facCode == 'upft' || sers[n].facCode == 'downft' || sers[n].facCode == 'ft') {
|
|
if (title == '上扶梯' || title == '下扶梯') {
|
|
title = '扶梯'
|
|
}
|
|
titleEn = Config.iconEn['扶梯']
|
|
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 == 'Sprite') {
|
|
let title = sers[n].userData.title
|
|
let titleEn = Config.iconEn[title]
|
|
let type = sers[n].facCode
|
|
let imgUrl = sers[n].imgUrl
|
|
if (sers[n].facCode == 'upft' || sers[n].facCode == 'downft' || sers[n].facCode == 'ft') {
|
|
title = '扶梯'
|
|
titleEn = Config.iconEn[title]
|
|
type = 'ft'
|
|
imgUrl = './static/img/ft.png'
|
|
}
|
|
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 1.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 1.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 Config.shopData) {
|
|
if (item.shopName === shopName) {
|
|
let toObj = { shopNum: item.houseNumber, node: item.yaxis }
|
|
for (let h = 0; h < Config.allMap.length; h++) {
|
|
let sArr = Config.allMap[h].buildArr
|
|
for (let i = 0; i < sArr.length; i++) {
|
|
let shops = Config.allMap[h].buildArr[i].mapData.shopArea
|
|
for (let k = 0; k < shops.length; k++) {
|
|
if (shops[k].name == toObj.shopNum) {
|
|
toObj.floor = i
|
|
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 1.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 = { node: '', xaxis: '', yaxis: '', floor: '', comeIn: '' }
|
|
let buildOrder = Config.selectBuild
|
|
let floorOrder = -1
|
|
if (obj.hasOwnProperty('build')) {
|
|
buildOrder = parseInt(obj.build)
|
|
}
|
|
if (obj.hasOwnProperty('floor')) {
|
|
floorOrder = parseInt(obj.floor)
|
|
}
|
|
let sArr = Config.allMap[buildOrder].buildArr
|
|
if (floorOrder != -1) {
|
|
if (type == 'shop') {
|
|
shopArr = sArr[floorOrder].mapData.shopArea
|
|
} else if (type == 'park') {
|
|
shopArr = sArr[floorOrder].mapData.parkArea
|
|
}
|
|
for (let k = 0; k < shopArr.length; k++) {
|
|
if (shopArr[k].name == obj.shopNum) {
|
|
reObj.floor = i
|
|
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
|
|
}
|
|
break
|
|
}
|
|
}
|
|
} else {
|
|
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.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
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return reObj
|
|
},
|
|
/**
|
|
* 模拟导航获取路线
|
|
*/
|
|
onFindPathModel: function (usePath = null) {
|
|
Map_QM.forShopArr.length = 0
|
|
_indexPathFloor = 0
|
|
isPathPlay = true
|
|
Map_QM.dispatchEvent({
|
|
type: 'startFindPath',
|
|
data: ''
|
|
})
|
|
if (parseInt(Config.startObj.node) == -1) {
|
|
return
|
|
}
|
|
if (!Config.startObj.xaxis) {
|
|
let pathData = Config.allMap[Config.selectBuild].buildArr[parseInt(Config.startObj.floor)].mapData.path
|
|
Config.startObj.xaxis = pathData.nodes[parseInt(Config.startObj.node)].x
|
|
Config.startObj.yaxis = pathData.nodes[parseInt(Config.startObj.node)].y
|
|
}
|
|
if (!usePath) {
|
|
usePath = graphPath
|
|
}
|
|
Map_QM.forShopPath(usePath)
|
|
},
|
|
forShopPath: function (usePath) {
|
|
let startNade = Config.selectBuild + '_' + Config.startObj.floor + '_' + Config.startObj.node
|
|
let toNade = Config.selectBuild + '_' + Config.overObj.floor + '_' + Config.overObj.node
|
|
let path = dijkstra.find_path(usePath, startNade, toNade)
|
|
let PathPoint = path.nodes
|
|
let Dir = '前方',
|
|
index = 0
|
|
let DirEn = 'forward'
|
|
this.forShopArr = []
|
|
if (PathPoint.length > 1) {
|
|
this.forShopArr.push({ floor: Config.startObj.floor, PathPoint: [] })
|
|
let pathData
|
|
for (let j = 0; j < PathPoint.length; j++) {
|
|
let array = PathPoint[j].split('_')
|
|
pathData = Config.allMap[Config.selectBuild].buildArr[parseInt(array[1])].mapData.path
|
|
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('_'))
|
|
} else {
|
|
this.forShopArr[index].Facilities = null
|
|
}
|
|
this.forShopArr.push({ 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 - Config.deviceObj.angle
|
|
|
|
ang = ang > 180 ? ang - 360 : ang
|
|
ang = ang < -180 ? ang + 360 : ang
|
|
|
|
if (ang < -50 && ang >= -130) {
|
|
Dir = '向前出发'
|
|
DirEn = 'forward'
|
|
} else if (ang >= -50 && ang < 50) {
|
|
Dir = '向右出发'
|
|
DirEn = 'right'
|
|
} else if (ang >= 50 && ang < 130) {
|
|
Dir = '向后出发'
|
|
DirEn = 'back'
|
|
} else {
|
|
Dir = '向左出发'
|
|
DirEn = 'left'
|
|
}
|
|
}
|
|
}
|
|
let pLen = Map_QM.forShopArr[Map_QM.forShopArr.length - 1].PathPoint.length
|
|
Config.overObj.xaxis = Map_QM.forShopArr[Map_QM.forShopArr.length - 1].PathPoint[pLen - 1].x
|
|
Config.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].floor, m)
|
|
if (Config.overObj.floor == Map_QM.forShopArr[m].floor) {
|
|
let len = Map_QM.forShopArr[m].wayShop.length
|
|
if (Map_QM.forShopArr[m].wayShop[len - 1]?.shop.yaxis == Config.overObj.node) {
|
|
Map_QM.forShopArr[m].wayShop.pop()
|
|
}
|
|
}
|
|
}
|
|
Map_QM.dispatchEvent({
|
|
type: 'initPathOver',
|
|
data: Map_QM.forShopArr
|
|
})
|
|
} else {
|
|
console.error('无可行路径,请检查起、终点位')
|
|
return
|
|
}
|
|
let mint = parseInt(path.cost / Config.mapScale / 55) < 0.5 ? 0.5 : parseInt(path.cost / Config.mapScale / 55)
|
|
//console.log(`距离目的地 ${parseInt(path.cost / Config.mapScale)} 米,预计${mint} 分钟`); // 21 是比例尺
|
|
this.onFindPathToObj()
|
|
},
|
|
/**
|
|
* 途径店铺
|
|
*/
|
|
foreignShop: function (pathArr, cFloor, m) {
|
|
let shopList = []
|
|
let shops = Map_QM.mapArr[Config.selectBuild][parseInt(cFloor)].allObj.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) {
|
|
let childs = this.mapArr[Config.selectBuild][fromFArr[1]].serObj.children
|
|
let selectEle
|
|
for (let i = 0; i < childs.length; i++) {
|
|
if (childs[i].navCode == fromFArr[2]) {
|
|
selectEle = { imgUrl: childs[i].imgUrl, userData: childs[i].userData, position: { x: childs[i].position.x, y: childs[i].position.y } }
|
|
break
|
|
}
|
|
}
|
|
return selectEle
|
|
},
|
|
|
|
/**
|
|
* 寻路动画方法
|
|
*/
|
|
onFindPathToObj: function () {
|
|
Map_QM.dispatchEvent({
|
|
//初始化寻路界面
|
|
type: 'initPathPage',
|
|
data: this.forShopArr
|
|
})
|
|
outTime = -1
|
|
_indexPathFloor = 0
|
|
Map_QM.callBackLoadOver = Map_QM.callBackForPathShop //楼层初始化完成后回调
|
|
|
|
if (Config.overlap) {
|
|
if (Map_QM.forShopArr.length == 2) {
|
|
Map_QM.changeFloorInner(Map_QM.forShopArr[0].floor, Map_QM.forShopArr[1].floor)
|
|
} else if (Map_QM.forShopArr.length == 3) {
|
|
Map_QM.changeFloorInner(Map_QM.forShopArr[0].floor, Map_QM.forShopArr[1].floor, Map_QM.forShopArr[2].floor)
|
|
} else {
|
|
Map_QM.changeFloorInner(Map_QM.forShopArr[_indexPathFloor].floor)
|
|
}
|
|
} else {
|
|
if (pathCameraState == '2D') {
|
|
Map_QM.onShowMeDir(2)
|
|
Map_QM.controls.enabled = false
|
|
Map_QM.guide = Map_QM.man_2d
|
|
}
|
|
Map_QM.changeFloorInner(Map_QM.forShopArr[_indexPathFloor].floor)
|
|
}
|
|
|
|
// let shopArr = Map_QM.mapArr[Config.selectBuild][parseInt(Config.overObj.floor)].allObj.children;
|
|
// if(Config.overObj.shopNum){ //匹配编号
|
|
// for (let k = 0; k < shopArr.length; k++) {
|
|
// if (shopArr[k].isMesh && shopArr[k].name == Config.overObj.shopNum) {
|
|
// Map_QM.overShop = shopArr[k];
|
|
// Map_QM.overShop.userData.material = shopArr[k].material;
|
|
// Map_QM.overShop.material = new THREE.MeshBasicMaterial({ color: 0xA0522D}); // 0xAD8164
|
|
// break;
|
|
// }
|
|
// }
|
|
// }else{//匹配导航点
|
|
// for (let k = 0; k < shopArr.length; k++) {
|
|
// if (shopArr[k].isMesh && parseInt(shopArr[k].node) === parseInt(Config.overObj.node)) {
|
|
// Map_QM.overShop = shopArr[k];
|
|
// Map_QM.overShop.userData.material = shopArr[k].material;
|
|
// Map_QM.overShop.material = new THREE.MeshBasicMaterial({ color: 0xA0522D});
|
|
// break;
|
|
// }
|
|
// }
|
|
// }
|
|
},
|
|
/**
|
|
* 播放楼层动画完成后
|
|
*/
|
|
callBackForPathShop: function () {
|
|
Map_QM.callBackLoadOver = null
|
|
Map_QM.dispatchEvent({
|
|
//开始播放寻路动画
|
|
type: 'startPlayPath',
|
|
data: this.forShopArr
|
|
})
|
|
Map_QM.onFindPath()
|
|
},
|
|
/**
|
|
* 寻路方法
|
|
* @param {Object} startN
|
|
* @param {Object} endN
|
|
*/
|
|
onFindPath: function () {
|
|
TweenMax.killAll(true)
|
|
if (Config.overlap) {
|
|
Map_QM.mapArr[Config.selectBuild][Config.overObj.floor].setOverSite(
|
|
Config.overObj.xaxis,
|
|
Config.overObj.yaxis,
|
|
Map_QM.mapArr[Config.selectBuild][Config.overObj.floor].allObj.position.y + parseInt(Config.shopHeight)
|
|
)
|
|
} else {
|
|
if (Config.overObj.floor == Config.selectFloor && Config.overObj.xaxis) {
|
|
Map_QM.mapArr[Config.selectBuild][Config.overObj.floor].setOverSite(
|
|
Config.overObj.xaxis,
|
|
Config.overObj.yaxis,
|
|
Map_QM.mapArr[Config.selectBuild][Config.overObj.floor].allObj.position.y + parseInt(Config.shopHeight)
|
|
)
|
|
}
|
|
}
|
|
|
|
if (Map_QM.forShopArr.length > 0) {
|
|
document.addEventListener('pathOver', Map_QM.onFindPathFloor, true)
|
|
if (Config.overlap && _indexPathFloor == 0) {
|
|
//叠层
|
|
for (let pathObj of Map_QM.forShopArr) {
|
|
Map_QM.mapArr[Config.selectBuild][pathObj.floor].findPath.onFindPathAnimation(pathObj.PathPoint, pathObj.floor) //传入数组
|
|
}
|
|
let extrudeSettings
|
|
let vects = new THREE.CurvePath()
|
|
let vects2 = new THREE.CurvePath()
|
|
if (Map_QM.forShopArr.length == 2) {
|
|
vects.add(
|
|
new THREE.LineCurve3(
|
|
new THREE.Vector3(
|
|
Map_QM.forShopArr[0].PathPoint[Map_QM.forShopArr[0].PathPoint.length - 1].x,
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[0].floor].allObj.position.y,
|
|
Map_QM.forShopArr[0].PathPoint[Map_QM.forShopArr[0].PathPoint.length - 1].y
|
|
),
|
|
new THREE.Vector3(
|
|
Map_QM.forShopArr[1].PathPoint[0].x,
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[1].floor].allObj.position.y,
|
|
Map_QM.forShopArr[1].PathPoint[0].y
|
|
)
|
|
)
|
|
)
|
|
extrudeSettings = { bevelEnabled: true, steps: 200, bevelSegments: 8, extrudePath: vects }
|
|
let geometry = new THREE.ExtrudeGeometry(Map_QM.shape, extrudeSettings)
|
|
let lineDashed = new THREE.Mesh(geometry, Config.tubeMaterial)
|
|
Map_QM.dtLineGroup.add(lineDashed)
|
|
}
|
|
if (Map_QM.forShopArr.length == 3) {
|
|
vects.add(
|
|
new THREE.LineCurve3(
|
|
new THREE.Vector3(
|
|
Map_QM.forShopArr[0].PathPoint[Map_QM.forShopArr[0].PathPoint.length - 1].x,
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[0].floor].allObj.position.y,
|
|
Map_QM.forShopArr[0].PathPoint[Map_QM.forShopArr[0].PathPoint.length - 1].y
|
|
),
|
|
new THREE.Vector3(
|
|
Map_QM.forShopArr[1].PathPoint[0].x,
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[1].floor].allObj.position.y,
|
|
Map_QM.forShopArr[1].PathPoint[0].y
|
|
)
|
|
)
|
|
)
|
|
|
|
vects2.add(
|
|
new THREE.LineCurve3(
|
|
new THREE.Vector3(
|
|
Map_QM.forShopArr[1].PathPoint[Map_QM.forShopArr[1].PathPoint.length - 1].x,
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[1].floor].allObj.position.y,
|
|
Map_QM.forShopArr[1].PathPoint[Map_QM.forShopArr[1].PathPoint.length - 1].y
|
|
),
|
|
new THREE.Vector3(
|
|
Map_QM.forShopArr[2].PathPoint[0].x,
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[2].floor].allObj.position.y,
|
|
Map_QM.forShopArr[2].PathPoint[0].y
|
|
)
|
|
)
|
|
)
|
|
extrudeSettings = { bevelEnabled: true, steps: 200, bevelSegments: 8, extrudePath: vects }
|
|
extrudeSettings2 = { bevelEnabled: true, steps: 200, bevelSegments: 8, extrudePath: vects2 }
|
|
let geometry = new THREE.ExtrudeGeometry(Map_QM.shape, extrudeSettings)
|
|
let lineDashed = new THREE.Mesh(geometry, Config.tubeMaterial)
|
|
Map_QM.dtLineGroup.add(lineDashed)
|
|
let geometry2 = new THREE.ExtrudeGeometry(Map_QM.shape, extrudeSettings2)
|
|
let lineDashed2 = new THREE.Mesh(geometry2, Config.tubeMaterial)
|
|
Map_QM.dtLineGroup.add(lineDashed2)
|
|
}
|
|
} else {
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[_indexPathFloor].floor].findPath.clearPath()
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[_indexPathFloor].floor].findPath.onFindPathAnimation(Map_QM.forShopArr[_indexPathFloor].PathPoint) //传入数组
|
|
}
|
|
Map_QM.mapArr[Config.selectBuild][Map_QM.forShopArr[_indexPathFloor].floor].findPath.guidePathPlay(Map_QM.forShopArr[_indexPathFloor])
|
|
Map_QM.collisionChock()
|
|
}
|
|
},
|
|
/**
|
|
* 显示楼层
|
|
*/
|
|
showNavFloor: function (fromFloor, toFloor) {
|
|
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[Config.selectBuild][i].floorName)
|
|
}
|
|
return floorArr
|
|
},
|
|
|
|
//导航完成事件
|
|
onFindPathFloor: function (event) {
|
|
document.removeEventListener('pathOver', Map_QM.onFindPathFloor)
|
|
if (Map_QM.forShopArr.length <= _indexPathFloor) {
|
|
return
|
|
}
|
|
Map_QM.dispatchEvent({
|
|
//当前层寻路完成
|
|
type: 'floorPlayOver',
|
|
data: Map_QM.forShopArr[_indexPathFloor].floor
|
|
})
|
|
if (_indexPathFloor < Map_QM.forShopArr.length - 1) {
|
|
let pathFloor = Map_QM.forShopArr[_indexPathFloor].floor
|
|
let x0 = Map_QM.forShopArr[_indexPathFloor].Facilities.position.x + 64
|
|
let y0 = Map_QM.forShopArr[_indexPathFloor].Facilities.position.y
|
|
let model = Map_QM.forShopArr[_indexPathFloor].Facilities.userData.model
|
|
let box
|
|
if (model && model.userData.name == 'dt') {
|
|
model.traverse(function (child) {
|
|
if (child.isMesh && child.name == 'zhitibox') {
|
|
box = child
|
|
}
|
|
})
|
|
}
|
|
let zo = 2,
|
|
tz = 2
|
|
let add = Config.is4k ? 80 : 40
|
|
_indexPathFloor++
|
|
let toFloor = parseInt(Map_QM.forShopArr[_indexPathFloor].floor)
|
|
Config.selectFloor = toFloor
|
|
if (pathFloor < toFloor) {
|
|
tz = (toFloor - pathFloor) * add
|
|
} else {
|
|
zo = (pathFloor - toFloor) * add
|
|
}
|
|
|
|
document.getElementById('moveFloor').style.bottom = zo + 'px'
|
|
document.getElementById('moveFloor').style.width = add + 'px'
|
|
document.getElementById('moveFloor').style.height = add + 'px'
|
|
let floorArr = Map_QM.showNavFloor(pathFloor, toFloor) //电梯旁显示的楼层名称
|
|
Map_QM.moveFloorbg.element.style.visibility = 'visible'
|
|
Map_QM.moveFloorbg.element.style.width = add + 8 + 'px'
|
|
Map_QM.moveFloorbg.element.style.height = floorArr.length * add + 'px'
|
|
Map_QM.moveFloorbg.position.set(x0, y0, 80)
|
|
Map_QM.moveFloorbg.applyMatrix(Map_QM.mapArr[Config.selectBuild][pathFloor].allObj.matrix)
|
|
Map_QM.moveFloorbg.applyMatrix(Map_QM.sceneGap.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 (Config.is4k) {
|
|
span2.style.fontSize = '32px'
|
|
}
|
|
span2.style.width = add + '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 () {
|
|
if (!Config.overlap) {
|
|
Map_QM.callBackLoadOver = Map_QM.callBackForPathShop //楼层初始化完成后回调
|
|
Map_QM.changeFloorInner(Map_QM.forShopArr[_indexPathFloor].floor)
|
|
} else {
|
|
if (Map_QM.forShopArr > _indexPathFloor) {
|
|
Config.selectFloor = Map_QM.forShopArr[_indexPathFloor].floor
|
|
}
|
|
Map_QM.clearFloor(-1, false)
|
|
Map_QM.callBackForPathShop()
|
|
}
|
|
}
|
|
}
|
|
)
|
|
if (box) {
|
|
TweenMax.fromTo(
|
|
box.position,
|
|
1.2,
|
|
{ y: zo / 3 },
|
|
{
|
|
y: tz / 3,
|
|
delay: 0.2,
|
|
onComplete: function () {
|
|
box.position.y = 0
|
|
}
|
|
}
|
|
)
|
|
}
|
|
|
|
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
|
|
|
|
let s = Math.sqrt((xt - Map_QM.guide.position.x) * (xt - Map_QM.guide.position.x) + (yt - Map_QM.guide.position.y) * (yt - Map_QM.guide.position.y))
|
|
let ang = Math.acos((yt - Map_QM.guide.position.y) / s)
|
|
if (xt < Map_QM.guide.position.x) {
|
|
Map_QM.guide.rotation.z = -1 * ang //Math.PI-ang;
|
|
} else {
|
|
Map_QM.guide.rotation.z = ang //Math.PI+ang;
|
|
}
|
|
|
|
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 {
|
|
Config.startObj = Config.deviceObj
|
|
//console.log("到达店铺");
|
|
Map_QM.dispatchEvent({
|
|
//寻路完成
|
|
type: 'PathPlayOver',
|
|
data: 'PathPlayOver'
|
|
})
|
|
}
|
|
},
|
|
/**
|
|
* 楼层状态清理
|
|
*/
|
|
clearFloor: function (fIndex = -1, reSet = true) {
|
|
if (fIndex == -1) {
|
|
fIndex = Config.deviceObj.floor
|
|
}
|
|
if (Map_QM.selectShop) {
|
|
Map_QM.selectShop.scale.z = 1
|
|
Map_QM.selectShop.material = Config.getMeshMaterial(Map_QM.selectShop.userData.shopData.formatColor || 0xeab16e)
|
|
}
|
|
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.visibility = 'hidden'
|
|
}
|
|
Map_QM.clearDeviceSelectState()
|
|
if (reSet) {
|
|
//叠层不处理
|
|
if (Map_QM.mapArr[Config.selectBuild] && Map_QM.mapArr[Config.selectBuild].length > 0) {
|
|
for (let i = 0; i < Map_QM.mapArr[Config.selectBuild].length; i++) {
|
|
let lines = Map_QM.mapArr[Config.selectBuild][i].lineObj
|
|
for (let j = lines.children.length - 1; j >= 0; j--) {
|
|
Map_QM.mapArr[Config.selectBuild][i].lineObj.remove(lines.children[j])
|
|
}
|
|
let child = Map_QM.mapArr[Config.selectBuild][i].allObj
|
|
for (let k = child.children.length - 1; k >= 0; k--) {
|
|
if (child.children[k].name == 'lineDash') {
|
|
Map_QM.mapArr[Config.selectBuild][i].allObj.remove(child.children[k])
|
|
}
|
|
}
|
|
Map_QM.mapArr[Config.selectBuild][i].findPath.clearPath()
|
|
}
|
|
}
|
|
Map_QM.remove_child(Map_QM.dtLineGroup)
|
|
}
|
|
TweenMax.killAll(true)
|
|
if (Map_QM.overShop) {
|
|
Map_QM.overShop.scale.z = 1
|
|
Map_QM.overShop.material = Map_QM.overShop.userData.material
|
|
}
|
|
},
|
|
|
|
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 1.0.0
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
*/
|
|
pathStop: function (isPlaying) {
|
|
isPathPlay = isPlaying === undefined ? !isPathPlay : isPlaying
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].findPath.pathPlay.isPlay = isPathPlay
|
|
},
|
|
/**
|
|
* @api {方法} pathRePlay() 导航动画重播
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 导航动画重播
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
*/
|
|
pathRePlay: function () {
|
|
if (Config.overObj && Map_QM.forShopArr[0]) {
|
|
clearTimeout(outTime)
|
|
outTime = setTimeout(() => {
|
|
clearTimeout(outTime)
|
|
isPathPlay = true
|
|
Map_QM.clearFloor()
|
|
Map_QM.onFindPathToObj()
|
|
}, 300)
|
|
}
|
|
},
|
|
|
|
/**
|
|
* @api {方法} ChangePathByFt() 切换扶梯模式
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 导航切换扶梯模式
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {function} callBack 回调函数
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.ChangePathByFt(function);
|
|
*
|
|
*/
|
|
ChangePathByFt: function (callBack) {
|
|
if (Config.overObj) {
|
|
clearTimeout(outTime)
|
|
outTime = setTimeout(() => {
|
|
clearTimeout(outTime)
|
|
Map_QM.clearFloor()
|
|
Map_QM.onFindPathModel(ftPath)
|
|
if (callBack) {
|
|
Map_QM.parseForShopArr()
|
|
const data = JSON.parse(JSON.stringify(forShopArr))
|
|
callBack(data)
|
|
}
|
|
}, 300)
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} ChangePathByDt() 切换电梯模式
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 导航切换电梯模式
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {function} callBack 回调函数
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.ChangePathByDt(function);
|
|
*
|
|
*/
|
|
ChangePathByDt: function (callBack) {
|
|
if (Config.overObj) {
|
|
clearTimeout(outTime)
|
|
outTime = setTimeout(() => {
|
|
clearTimeout(outTime)
|
|
Map_QM.clearFloor()
|
|
Map_QM.onFindPathModel(dtPath)
|
|
if (callBack) {
|
|
Map_QM.parseForShopArr()
|
|
const data = JSON.parse(JSON.stringify(forShopArr))
|
|
callBack(data)
|
|
}
|
|
}, 300)
|
|
}
|
|
},
|
|
/**
|
|
* @api {方法} ChangePathByGood() 切换最佳模式
|
|
* @apiGroup 地图导航
|
|
* @apiDescription 导航切换最佳模式
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {function} callBack 回调函数
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.ChangePathByGood(function);
|
|
*
|
|
*/
|
|
ChangePathByGood: function (callBack) {
|
|
if (Config.overObj) {
|
|
clearTimeout(outTime)
|
|
outTime = setTimeout(() => {
|
|
clearTimeout(outTime)
|
|
Map_QM.clearFloor()
|
|
Map_QM.onFindPathModel(graphPath)
|
|
if (callBack) {
|
|
Map_QM.parseForShopArr()
|
|
const data = JSON.parse(JSON.stringify(forShopArr))
|
|
callBack(data)
|
|
}
|
|
}, 300)
|
|
}
|
|
},
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
/**
|
|
* @api {方法} changeWindowResize() 窗口变化
|
|
* @apiGroup 地图交互
|
|
* @apiDescription 窗口变化
|
|
* @apiVersion 1.0.0
|
|
*
|
|
* @apiParam {int} width 窗口宽
|
|
* @apiParam {int} height 窗口高
|
|
*
|
|
* @apiSampleRequest off
|
|
*
|
|
* @apiParamExample 请求示例
|
|
*
|
|
* Map_QM.changeWindowResize(1280,1080);
|
|
*/
|
|
changeWindowResize: function (width = -1, height = -1) {
|
|
aspect = width / height
|
|
cameraPerspective.aspect = aspect
|
|
cameraPerspective.updateProjectionMatrix()
|
|
cameraOrtho.left = (340 * aspect) / -2
|
|
cameraOrtho.right = (340 * aspect) / 2
|
|
cameraOrtho.top = 340 / 2
|
|
cameraOrtho.bottom = 340 / -2
|
|
cameraOrtho.updateProjectionMatrix()
|
|
|
|
Map_QM.renderer.setSize(width, height)
|
|
Map_QM.labelRenderer.setSize(width, height)
|
|
Map_QM.w = width
|
|
Map_QM.h = height
|
|
}
|
|
}
|
|
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.labelObj = new THREE.Group()
|
|
this.labelObj.renderOrder = 100
|
|
this.iconLabel = new THREE.Group()
|
|
this.iconLabel.renderOrder = 100
|
|
|
|
this.floorOrder = fIndex
|
|
this.buildOrder = bIndex
|
|
this.floorName = floorName
|
|
|
|
//存放设施图标
|
|
this.serObj = new THREE.Object3D()
|
|
//存放车位box
|
|
this.parkObj = new THREE.Group()
|
|
//标签
|
|
this.tagObj = new THREE.Group()
|
|
this.tagObj.renderOrder = 100
|
|
this.devObj = new THREE.Group()
|
|
//存放设施图标
|
|
this.logoObj = new THREE.Object3D()
|
|
this.allObj.add(this.logoObj)
|
|
this.svgObj = new THREE.Group()
|
|
this.allObj.add(this.svgObj)
|
|
this.allObj.add(this.serObj)
|
|
this.allObj.add(this.devObj)
|
|
this.allObj.add(this.labelObj)
|
|
this.allObj.add(this.iconLabel)
|
|
this.allObj.add(this.tagObj)
|
|
//标签
|
|
this.showTagObj = new THREE.Group()
|
|
this.showTagObj.renderOrder = 100
|
|
this.allObj.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.initDevice() //初始化设备
|
|
this.initStairs()
|
|
this.initTextArea()
|
|
this.initWall()
|
|
this.initDecos()
|
|
this.initPark()
|
|
this.initModel()
|
|
this.initTree() //植树
|
|
},
|
|
initModel: function () {
|
|
let sopce = this
|
|
if (Config.modelArr) {
|
|
for (let i = 0; i < Config.modelArr.length; i++) {
|
|
if (Config.modelArr[i].floor == this.floorOrder) {
|
|
new THREE.GLTFLoader().load(Config.modelArr[i].url, function (object) {
|
|
//加载路径fbx文件
|
|
let mod = object.scene
|
|
mod.traverse(function (child) {
|
|
if (child.isMesh) {
|
|
child.receiveShadow = true
|
|
child.castShadow = true
|
|
if (child.material.map) {
|
|
child.material.map.encoding = THREE.LinearEncoding //贴图需要转换成 线性编码
|
|
}
|
|
child.material.color.convertGammaToLinear(0.7)
|
|
}
|
|
})
|
|
for (let t = 0; t < Config.modelArr[i].list.length; t++) {
|
|
let obj = mod.clone()
|
|
obj.position.set(Config.modelArr[i].list[t].site.x, -1 * Config.modelArr[i].list[t].site.y, Config.modelArr[i].list[t].site.z)
|
|
obj.scale.set(Config.modelArr[i].list[t].size.x, Config.modelArr[i].list[t].size.y, Config.modelArr[i].list[t].size.z)
|
|
obj.rotateX(Config.modelArr[i].list[t].rot.x)
|
|
obj.rotateY(Config.modelArr[i].list[t].rot.y)
|
|
obj.rotateZ(Config.modelArr[i].list[t].rot.z)
|
|
sopce.allObj.add(obj)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
if (Config.labelIconArr) {
|
|
for (let i = 0; i < Config.labelIconArr.length; i++) {
|
|
if (Config.labelIconArr[i].floor == this.floorOrder) {
|
|
let SpriteDiv = document.createElement('div')
|
|
SpriteDiv.className = Config.labelIconArr[i].className
|
|
SpriteDiv.innerHTML = Config.labelIconArr[i].title
|
|
SpriteDiv.dataset.id = Config.labelIconArr[i].data.id
|
|
SpriteDiv.dataset.x = Config.labelIconArr[i].site.x
|
|
SpriteDiv.dataset.y = Config.labelIconArr[i].site.y
|
|
SpriteDiv.dataset.z = Config.labelIconArr[i].site.z
|
|
let pointLabel = new THREE.CSS2DObject(SpriteDiv)
|
|
pointLabel.position.set(Config.labelIconArr[i].site.x, -1 * Config.labelIconArr[i].site.y, Config.labelIconArr[i].site.z)
|
|
pointLabel.name = Config.labelIconArr[i].title
|
|
pointLabel.userData = Config.labelIconArr[i].data
|
|
pointLabel.userData.site = Config.labelIconArr[i].site
|
|
if (Config.labelIconArr[i].click) {
|
|
//可点击
|
|
SpriteDiv.addEventListener(
|
|
'click',
|
|
event => {
|
|
Map_QM.dispatchEvent({
|
|
type: 'labelIcon',
|
|
data: event.target.dataset
|
|
})
|
|
},
|
|
false
|
|
)
|
|
}
|
|
pointLabel.userData.floor = Config.labelIconArr[i].floor
|
|
sopce.showTagObj.add(pointLabel)
|
|
pointLabel.userData.show = Config.labelIconArr[i].data.show
|
|
if (Config.labelIconArr[i].data.show != language) {
|
|
pointLabel.element.style.opacity = 0
|
|
pointLabel.element.style.pointerEvents = 'none'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
initTree: function () {
|
|
let mapData = Config.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
|
|
if (mapData.models) {
|
|
for (let t = 0; t < mapData.models.length; t++) {
|
|
for (let i = 0; i < Config.fbxModels.length; i++) {
|
|
if (mapData.models[t].type == Config.fbxModels[i].key) {
|
|
let obj = Config.fbxModels[i].obj.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(Config.fbxModels[i].operation.rot.x)
|
|
obj.rotateY((-1 * mapData.models[t].angle * Math.PI) / 180)
|
|
this.allObj.add(obj)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
//初始化单楼层
|
|
initFloor: function () {
|
|
let floor
|
|
let mapData = Config.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
|
|
let entColor, borderColor
|
|
if (mapData.floorArea) {
|
|
floor = Config.changeAreaToString(mapData.floorArea)
|
|
}
|
|
let bLen = mapData.buildArea.length
|
|
let hLen = mapData.hollowArea.length
|
|
let hows_f = []
|
|
for (let m = 0; m < hLen; m++) {
|
|
hows_f.push(Config.changeAreaToString(mapData.hollowArea[m]))
|
|
}
|
|
if (floor) {
|
|
entColor = parseInt(mapData.floorArea.entColor.replace('#', '0x'), 16)
|
|
borderColor = parseInt(mapData.floorArea.borderColor.replace('#', '0x'), 16)
|
|
floorH = parseInt(mapData.floorArea.toHeight)
|
|
let mash = this.Model_QM.MyModelShape(floor, hows_f, mapData.floorArea, entColor, borderColor, 10)
|
|
mash.receiveShadow = true
|
|
mash.castShadow = false
|
|
mash.userData = {
|
|
type: 'floor',
|
|
order: this.floorOrder
|
|
}
|
|
mash.name = 'floor'
|
|
this.allObj.add(mash)
|
|
}
|
|
/////////////////////初始化楼栋
|
|
for (let i = 0; i < bLen; i++) {
|
|
let build = Config.changeAreaToString(mapData.buildArea[i])
|
|
let hows = []
|
|
for (let t = 0; t < hLen; t++) {
|
|
let isIn = Config.checkAreaInArea(mapData.hollowArea[t], mapData.buildArea[i])
|
|
if (isIn) {
|
|
hows.push(Config.changeAreaToString(mapData.hollowArea[t]))
|
|
}
|
|
}
|
|
entColor = parseInt(mapData.buildArea[i].entColor.replace('#', '0x'), 16)
|
|
borderColor = parseInt(mapData.buildArea[i].borderColor.replace('#', '0x'), 16)
|
|
Config.buildHeight = Math.max(parseInt(mapData.buildArea[i].toHeight), Config.buildHeight)
|
|
buildH = parseInt(mapData.buildArea[i].toHeight)
|
|
let mash = this.Model_QM.MyModelShape(build, hows, mapData.buildArea[i], entColor, borderColor, 30)
|
|
mash.receiveShadow = true
|
|
mash.castShadow = false
|
|
mash.userData = {
|
|
type: 'build',
|
|
order: this.floorOrder
|
|
}
|
|
mash.name = 'floor'
|
|
this.allObj.add(mash)
|
|
}
|
|
//店铺
|
|
let sLen = mapData.shopArea.length
|
|
for (let i = 0; i < sLen; i++) {
|
|
if (Config.changeAreaToString(mapData.shopArea[i]) != '') {
|
|
let arr = Config.changeShopLinesToString(mapData.shopArea[i])
|
|
|
|
entColor = mapData.shopArea[i].entColor || '#b79266'
|
|
borderColor = mapData.shopArea[i].borderColor || '#b79266'
|
|
let show = (showE = '')
|
|
let logo = '',
|
|
navRecommend = false,
|
|
shopD = {}
|
|
Config.shopHeight = parseInt(mapData.shopArea[i].toHeight)
|
|
let shopData = Config.shopData
|
|
if (shopData) {
|
|
for (let h = 0; h < shopData.length; h++) {
|
|
if (shopData[h].buildingOrder == this.buildOrder && shopData[h].floorOrder == this.floorOrder) {
|
|
if (shopData[h].houseNumber == mapData.shopArea[i].name) {
|
|
show = shopData[h].shopName
|
|
showE = shopData[h].shopNameEn
|
|
logo = shopData[h].logoUrl
|
|
if (shopData[h].isPass == undefined) {
|
|
navRecommend = true
|
|
} else {
|
|
navRecommend = shopData[h].isPass
|
|
}
|
|
shopD = shopData[h]
|
|
if (shopData[h].isNewShop) {
|
|
//新店
|
|
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 })
|
|
}
|
|
if (shopData[h].formatColor) {
|
|
entColor = parseInt(shopData[h].formatColor.replace('#', '0x'), 16)
|
|
} else {
|
|
entColor = '#eab16e'
|
|
}
|
|
if (shopData[h].borderColor) {
|
|
borderColor = parseInt(shopData[h].borderColor.replace('#', '0x'), 16)
|
|
} else {
|
|
borderColor = '#eab16e'
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (mapData.shopArea[i].logoUrl && mapData.shopArea[i].isLabel == 0) {
|
|
//添加logo
|
|
this.logoUtil.renderIcon(mapData.shopArea[i], this, parseInt(mapData.shopArea[i].toHeight) + 1)
|
|
} else {
|
|
//添加文字
|
|
if (show != '') {
|
|
let shopDiv = document.createElement('div')
|
|
shopDiv.className = 'shopLabel'
|
|
shopDiv.innerText = show
|
|
shopDiv.dataset.name = show
|
|
shopDiv.dataset.nameEn = showE
|
|
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))
|
|
this.labelObj.add(shopLabel)
|
|
shopLabel.element.style.pointerEvents = 'none'
|
|
}
|
|
}
|
|
let mahc = this.Model_QM.MyModelShape(arr, null, 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,
|
|
navRecommend: navRecommend,
|
|
type: 'shop',
|
|
entColor: entColor,
|
|
shopNum: mapData.shopArea[i].name,
|
|
shopName: show,
|
|
logo: logo,
|
|
borderColor: borderColor
|
|
}
|
|
show = show == 'shop' ? '' : show
|
|
show = show == 'floor' ? '' : show
|
|
show = show == 'build' ? '' : show
|
|
mahc.shopName = show
|
|
mahc.xaxis = mapData.shopArea[i].xaxis >> 0
|
|
mahc.yaxis = mapData.shopArea[i].yaxis >> 0
|
|
this.allObj.add(mahc)
|
|
}
|
|
}
|
|
},
|
|
addTagLabel: function (obj, userData) {
|
|
let shopDiv = document.createElement('img')
|
|
shopDiv.src = './static/img/' + obj.type + '.png'
|
|
shopDiv.style.zIndex = 200
|
|
let shopLabel = new THREE.CSS2DObject(shopDiv)
|
|
shopLabel.userData = userData
|
|
shopLabel.position.set(obj.xaxis >> 0, (-1 * obj.yaxis) >> 0, Config.shopHeight)
|
|
this.tagObj.add(shopLabel)
|
|
},
|
|
//初始化服务图标
|
|
initFacilitie: function () {
|
|
let serArr = Config.allMap[this.buildOrder].buildArr[this.floorOrder].mapData.icons
|
|
for (let i = 0; i < serArr.length; i++) {
|
|
serArr[i].floorOrder = this.floorOrder
|
|
this.facUtil.renderIcon(serArr[i], this)
|
|
}
|
|
},
|
|
//初始化设备图标
|
|
initDevice: function () {
|
|
let mapData = Config.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
|
|
if (deviceShow && deviceJSON && deviceJSON[this.buildOrder]) {
|
|
for (item of deviceJSON[this.buildOrder].floors) {
|
|
if (item.floorOrder == this.floorOrder) {
|
|
let devices = item.devices
|
|
for (let i = 0; i < devices.length; i++) {
|
|
if (devices[i].yaxis != '' && mapData.path.nodes[parseInt(devices[i].yaxis)]) {
|
|
devices[i].x = mapData.path.nodes[parseInt(devices[i].yaxis)].x
|
|
devices[i].y = mapData.path.nodes[parseInt(devices[i].yaxis)].y
|
|
devices[i].node = parseInt(devices[i].yaxis)
|
|
this.facUtil.renderDeviceIcon(devices[i], this)
|
|
}
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
},
|
|
//初始化电梯图标
|
|
initStairs: function () {
|
|
let facArr = Config.allMap[this.buildOrder].buildArr[this.floorOrder].mapData.stairs
|
|
for (let i = 0; i < facArr.length; i++) {
|
|
if (facArr[i].facCode == 'upft') {
|
|
if (elevator) {
|
|
let ex = elevator.clone()
|
|
ex.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site)
|
|
ex.rotation.y = (facArr[i].angle * Math.PI) / -180
|
|
ex.userData.type = 'icon'
|
|
ex.userData.use = '3d'
|
|
ex.userData.name = 'upft'
|
|
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 (elevatorDown) {
|
|
let ex = elevatorDown.clone()
|
|
ex.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site)
|
|
ex.rotation.y = (facArr[i].angle * Math.PI) / -180
|
|
ex.userData.type = 'icon'
|
|
ex.userData.use = '3d'
|
|
ex.userData.name = 'downft'
|
|
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 (straight) {
|
|
let stra = straight.clone()
|
|
stra.position.set(facArr[i].x, -1 * facArr[i].y, facArr[i].site)
|
|
stra.rotation.y = (facArr[i].angle * Math.PI) / -180
|
|
stra.userData.type = 'icon'
|
|
stra.userData.use = '3d'
|
|
stra.userData.name = 'dt'
|
|
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 = Config.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 && Config.changeAreaToString(mapData.decos[i]) != '') {
|
|
let arr = Config.changeAreaToString(mapData.decos[i])
|
|
entColor = parseInt(mapData.decos[i].entColor.replace('#', '0x'), 16)
|
|
borderColor = parseInt(mapData.decos[i].borderColor.replace('#', '0x'), 16)
|
|
let show = mapData.decos[i].name == 'deco' ? '' : mapData.decos[i].name
|
|
let mahc = this.Model_QM.MyModelShape(arr, null, 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
|
|
}
|
|
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
|
|
gp.scale.set(mapData.groupArea[k].scale, mapData.groupArea[k].scale, mapData.groupArea[k].scale)
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < sLen; i++) {
|
|
if ((!mapData.decos[i].gid || mapData.decos[i].gid == '') && Config.changeAreaToString(mapData.decos[i]) != '') {
|
|
let arr = Config.changeAreaToString(mapData.decos[i])
|
|
entColor = parseInt(mapData.decos[i].entColor.replace('#', '0x'), 16)
|
|
borderColor = parseInt(mapData.decos[i].borderColor.replace('#', '0x'), 16)
|
|
let show = mapData.decos[i].name == 'deco' ? '' : mapData.decos[i].name
|
|
let mahc = this.Model_QM.MyModelShape(arr, null, 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
|
|
}
|
|
this.allObj.add(mahc)
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* 渲染墙体
|
|
*/
|
|
initWall: function () {
|
|
let mapData = Config.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
|
|
//渲染
|
|
if (mapData.wallArea) {
|
|
let sLen = mapData.wallArea.length
|
|
for (let i = 0; i < sLen; i++) {
|
|
let arr = Config.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'
|
|
}
|
|
this.allObj.add(mahc)
|
|
}
|
|
}
|
|
},
|
|
/**
|
|
* 渲染文本
|
|
*/
|
|
initTextArea: function () {
|
|
let mapData = Config.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.applyMatrix(Map_QM.sceneGap.matrix)
|
|
if (Map_QM.endIcon) {
|
|
Map_QM.endIcon.visible = pathCameraState == '2D' ? true : false
|
|
Map_QM.endIcon.scale.x = Map_QM.endIcon.scale.y = Map_QM.endIcon.scale.z = 100
|
|
Map_QM.endIcon.position.set(shopX, shopZ, shopY) //x,z,y
|
|
Map_QM.endIcon.applyMatrix(Map_QM.sceneGap.matrix)
|
|
}
|
|
} else {
|
|
let loader2 = new THREE.GLTFLoader()
|
|
loader2.load('./static/img/zhong.gltf', function (collada2) {
|
|
collada2.scene.traverse(function (child2) {
|
|
if (
|
|
child2.name == 'object_1' ||
|
|
child2.name == 'object_2' ||
|
|
child2.name == 'object_3' ||
|
|
child2.name == 'object_4' ||
|
|
child2.name == 'object_6' ||
|
|
child2.name == 'object_11' ||
|
|
child2.name == 'object_21' ||
|
|
child2.name == 'object_31' ||
|
|
child2.name == 'object_41'
|
|
) {
|
|
child2.material = new THREE.MeshBasicMaterial({ color: 0xff464e, transparent: true })
|
|
}
|
|
if (child2.name == 'object_5' || child2.name == 'object_51') {
|
|
child2.material = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true })
|
|
}
|
|
})
|
|
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.applyMatrix(Map_QM.sceneGap.matrix)
|
|
collada2.scene.renderOrder = 200
|
|
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('./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(80, 80, 1)
|
|
Map_QM.endIcon.center = new THREE.Vector2(0.5, 0)
|
|
Map_QM.endIcon.position.set(shopX, shopZ, shopY)
|
|
Map_QM.endIcon.applyMatrix(Map_QM.sceneGap.matrix)
|
|
Map_QM.endIcon.renderOrder = 300
|
|
Map_QM.endIcon.visible = pathCameraState == '2D' ? true : false
|
|
Map_QM.scene.add(Map_QM.endIcon)
|
|
}
|
|
},
|
|
/**
|
|
* 设置起点图标
|
|
*/
|
|
setStartSite: function (shopX, shopY, shopZ) {
|
|
let _this = this
|
|
new THREE.GLTFLoader().load('./static/img/qi.gltf', function (collada) {
|
|
//console.log(collada);
|
|
collada.scene.traverse(function (child) {
|
|
if (child.name == 'object_1' || child.name == 'object_3' || child.name == 'object_4' || child.name == 'object_31' || child.name == 'object_41') {
|
|
child.material = new THREE.MeshBasicMaterial({ color: 0xffae43, transparent: true })
|
|
}
|
|
if (child.name == 'object_2' || child.name == 'object_21') {
|
|
child.material = new THREE.MeshBasicMaterial({ color: 0xffffff, transparent: true })
|
|
}
|
|
})
|
|
collada.scene.scale.x = collada.scene.scale.y = collada.scene.scale.z = 100
|
|
collada.scene.rotateX(Math.PI / 2)
|
|
if (shopX != 0 && shopY != 0) {
|
|
collada.scene.position.set(shopX, -1 * shopY, shopZ) //x,z,y
|
|
}
|
|
collada.scene.renderOrder = 200
|
|
Map_QM.qiModel = collada.scene
|
|
if (Config.cameraDist.state == '2D') {
|
|
Map_QM.qiModel.visible = false
|
|
}
|
|
_this.allObj.add(collada.scene)
|
|
//--------------------------------------------------------------
|
|
let spriteMap = new THREE.TextureLoader().load('./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(80, 80, 1)
|
|
Map_QM.qiIcon.center = new THREE.Vector2(0.5, 0)
|
|
Map_QM.qiIcon.position.set(shopX, -1 * shopY, shopZ)
|
|
Map_QM.qiIcon.renderOrder = 300
|
|
Map_QM.qiIcon.visible = false
|
|
_this.allObj.add(Map_QM.qiIcon)
|
|
|
|
let spriteMap2 = new THREE.TextureLoader().load('./static/img/site.png')
|
|
let spriteMaterial2 = new THREE.SpriteMaterial({
|
|
//sizeAttenuation: false 禁止跟随鼠标缩放
|
|
map: spriteMap2,
|
|
depthTest: true,
|
|
transparent: true,
|
|
alphaTest: 0.5
|
|
})
|
|
Map_QM.dirIcon = new MySprite_QM(spriteMaterial2)
|
|
Map_QM.dirIcon.scale.set(160, 160, 1)
|
|
Map_QM.dirIcon.center = new THREE.Vector2(0.5, 0.5)
|
|
Map_QM.dirIcon.position.set(shopX, -1 * shopY, shopZ)
|
|
Map_QM.dirIcon.renderOrder = 300
|
|
if (Config.cameraDist.state == '3D') {
|
|
Map_QM.dirIcon.visible = false
|
|
}
|
|
_this.allObj.add(Map_QM.dirIcon)
|
|
})
|
|
},
|
|
/**
|
|
* 查找线
|
|
* @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 = Config.allMap[this.buildOrder].buildArr[this.floorOrder].mapData
|
|
//渲染车位
|
|
if (mapData.parkArea) {
|
|
let sLen = mapData.parkArea.length
|
|
if (sLen > 0) {
|
|
this.allObj.add(this.parkObj)
|
|
}
|
|
for (let i = 0; i < sLen; i++) {
|
|
if (Config.changeParkToString(mapData.parkArea[i]) != '') {
|
|
let arr = Config.changeParkToString(mapData.parkArea[i])
|
|
mapData.parkArea[i].alphaModle = 95
|
|
let mahc = this.Model_QM.MyParkShape(arr, mapData.parkArea[i], mapData.parkArea[i].entColor, mapData.parkArea[i].borderColor, 80)
|
|
this.parkObj.add(mahc)
|
|
mahc.xaxis = mapData.parkArea[i].xaxis >> 0
|
|
mahc.yaxis = mapData.parkArea[i].yaxis >> 0
|
|
mahc.node = mapData.parkArea[i].shopNav
|
|
mahc.userData = {
|
|
xaxis: mahc.xaxis,
|
|
yaxis: mahc.yaxis,
|
|
node: mahc.node,
|
|
floor: this.floorOrder,
|
|
shopNum: mahc.name,
|
|
type: 'park'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 渲染3D模型类
|
|
* 传入区域点list
|
|
* 镂空点 howllowArr
|
|
* 模型对象 options
|
|
*/
|
|
MyModel_QM = function () {
|
|
this.xaxis = 0
|
|
this.yaxis = 0
|
|
this.node = 0
|
|
}
|
|
//渲染平面车位
|
|
MyModel_QM.prototype.MyParkShape = function (areaArr, opObj, entityColor = 0xdadada, lineColor = 0xeeeeee, indexOrder = 1) {
|
|
let len = areaArr.length
|
|
if (len == 0) {
|
|
return
|
|
}
|
|
// 实例化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 < Config.lineBasicMaterialArr.length; k++) {
|
|
let color2 = new THREE.Color(lineColor)
|
|
if (Config.lineBasicMaterialArr[k].color.equals(color2)) {
|
|
material = Config.lineBasicMaterialArr[k]
|
|
}
|
|
}
|
|
if (!material) {
|
|
material = new THREE.LineBasicMaterial({
|
|
color: lineColor
|
|
}) //材质对象lineColor
|
|
Config.lineBasicMaterialArr.push(material)
|
|
}
|
|
|
|
let scanGeometry = new THREE.ShapeBufferGeometry(shape, 1)
|
|
if (opObj.angleY || opObj.angleZ) {
|
|
Config.rotateYZ(scanGeometry, (opObj.angleY * Math.PI) / 180, (opObj.angleZ * Math.PI) / 180)
|
|
}
|
|
// 创建模型
|
|
let mesh = new THREE.Mesh(scanGeometry, Config.parkMaterial)
|
|
let cubeEdges = new THREE.EdgesGeometry(scanGeometry, 1)
|
|
mesh.add(new THREE.Line(cubeEdges, material))
|
|
mesh.position.z = opObj.site || 3
|
|
mesh.renderOrder = indexOrder
|
|
mesh.name = opObj.name || ''
|
|
|
|
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
|
|
for (let k = 0; k < Config.lineBasicMaterialArr.length; k++) {
|
|
let color2 = new THREE.Color(lineColor)
|
|
if (Config.lineBasicMaterialArr[k].color.equals(color2)) {
|
|
material = Config.lineBasicMaterialArr[k]
|
|
}
|
|
}
|
|
if (!material) {
|
|
material = new THREE.LineBasicMaterial({
|
|
color: lineColor
|
|
}) //材质对象lineColor
|
|
Config.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: 24
|
|
}
|
|
|
|
scanGeometry = new THREE.ExtrudeGeometry(shape, options)
|
|
for (let e = 0; e < Config.meshMaterialArr.length; e++) {
|
|
let color2 = new THREE.Color(entityColor)
|
|
if (Config.meshMaterialArr[e].color.equals(color2) && Config.meshMaterialArr[e].opacity == alphaModle) {
|
|
meshMaterial = Config.meshMaterialArr[e]
|
|
}
|
|
}
|
|
if (!meshMaterial) {
|
|
meshMaterial = new THREE.MeshPhongMaterial({
|
|
//MeshStandardMaterial MeshPhongMaterial
|
|
color: entityColor,
|
|
transparent: true,
|
|
opacity: alphaModle,
|
|
side: THREE.DoubleSide,
|
|
depthTest: true
|
|
})
|
|
//meshMaterial.color.convertLinearToGamma(0.4);
|
|
Config.meshMaterialArr.push(meshMaterial)
|
|
}
|
|
if (opObj.angleY || opObj.angleZ) {
|
|
Config.rotateYZ(scanGeometry, (opObj.angleY * Math.PI) / 180, (opObj.angleZ * Math.PI) / 180)
|
|
}
|
|
// 创建模型
|
|
let mesh = new THREE.Mesh(scanGeometry, meshMaterial)
|
|
if (!Config.toMapModel && 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.MyModelText = function (svgArea) {
|
|
let text = svgArea.data
|
|
const paths = new THREE.SVGLoader().parse(text).paths
|
|
const group = new THREE.Group()
|
|
|
|
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.position.x = parseInt(svgArea.xaxis)
|
|
group.position.y = -1 * parseInt(svgArea.yaxis)
|
|
group.position.z = parseInt(svgArea.site)
|
|
group.scale.y *= -1
|
|
|
|
let meshMaterial
|
|
for (let e = 0; e < Config.meshMaterialArr.length; e++) {
|
|
let color2 = new THREE.Color().setHex(svgArea.entColor)
|
|
if (Config.meshMaterialArr[e].color.equals(color2) && Config.meshMaterialArr[e].opacity == svgArea.alphaModle) {
|
|
meshMaterial = Config.meshMaterialArr[e]
|
|
}
|
|
}
|
|
if (!meshMaterial) {
|
|
meshMaterial = new THREE.MeshStandardMaterial({
|
|
color: svgArea.entColor,
|
|
opacity: parseInt(svgArea.alphaModle) / 100
|
|
})
|
|
Config.meshMaterialArr.push(meshMaterial)
|
|
}
|
|
|
|
for (let i = 0; i < paths.length; i++) {
|
|
const path = paths[i]
|
|
let shapes = path.toShapes(true)
|
|
for (let j = 0; j < shapes.length; j++) {
|
|
const shape = shapes[j]
|
|
const geometry = new THREE.ExtrudeBufferGeometry(shape, {
|
|
depth: svgArea.toHeight,
|
|
bevelEnabled: false,
|
|
curveSegments: 24
|
|
})
|
|
const mesh = new THREE.Mesh(geometry, meshMaterial)
|
|
mesh.renderOrder = 50
|
|
mesh.name = svgArea.name || ''
|
|
mesh.position.set(-svgArea.width / 2, -svgArea.height / 2, 0)
|
|
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.site = parseInt(obj.site) || Config.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 () {}
|
|
|
|
Facilities_QM.prototype.renderIcon = function (obj, _this, isShow = true, ele = null) {
|
|
if (obj) {
|
|
let spriteMaterial
|
|
let url = './static/img/' + obj.facCode + '.png'
|
|
for (let m = 0; m < Config.spriteMaterialArr.length; m++) {
|
|
if (Config.spriteMaterialArr[m].name == obj.facCode) {
|
|
spriteMaterial = Config.spriteMaterialArr[m]
|
|
}
|
|
}
|
|
if (!spriteMaterial) {
|
|
let spriteMap = new THREE.TextureLoader().load(url)
|
|
spriteMaterial = new THREE.SpriteMaterial({
|
|
//sizeAttenuation: false 禁止跟随鼠标缩放
|
|
map: spriteMap,
|
|
depthTest: true,
|
|
transparent: true
|
|
})
|
|
spriteMaterial.name = obj.facCode
|
|
Config.spriteMaterialArr.push(spriteMaterial)
|
|
}
|
|
|
|
let sprite = new MySprite_QM(spriteMaterial, obj)
|
|
sprite.scale.set(64, 64, 1)
|
|
sprite.imgUrl = url
|
|
sprite.center = new THREE.Vector2(0.5, 0)
|
|
sprite.userData = obj
|
|
sprite.userData.type = 'icon'
|
|
sprite.userData.use = ele ? '2d' : 'all'
|
|
sprite.userData.model = ele
|
|
sprite.position.set(obj.x, -1 * obj.y, obj.site || Config.shopHeight + 1)
|
|
sprite.renderOrder = 300
|
|
sprite.visible = isShow
|
|
_this.serObj.add(sprite)
|
|
if (iconNameShow) {
|
|
let shopDiv = document.createElement('div')
|
|
shopDiv.className = 'shopLabel'
|
|
shopDiv.style.fontSize = '12px'
|
|
shopDiv.style.height = '14px'
|
|
shopDiv.innerText = obj.title
|
|
shopDiv.dataset.name = obj.title
|
|
shopDiv.dataset.nameEn = Config.iconEn[obj.title]
|
|
let shopLabel = new THREE.CSS2DObject(shopDiv)
|
|
shopLabel.position.set(obj.x, -1 * obj.y, 30)
|
|
_this.iconLabel.add(shopLabel)
|
|
shopLabel.element.style.pointerEvents = 'none'
|
|
}
|
|
}
|
|
}
|
|
Facilities_QM.prototype.renderDeviceIcon = function (obj, _this) {
|
|
if (obj) {
|
|
let spriteMaterial
|
|
let url = './static/img/deviceDir.png'
|
|
for (let m = 0; m < Config.spriteMaterialArr.length; m++) {
|
|
if (Config.spriteMaterialArr[m].name == 'deviceDir') {
|
|
spriteMaterial = Config.spriteMaterialArr[m]
|
|
}
|
|
}
|
|
if (!spriteMaterial) {
|
|
let spriteMap = new THREE.TextureLoader().load(url)
|
|
spriteMaterial = new THREE.MeshPhongMaterial({
|
|
//sizeAttenuation: false 禁止跟随鼠标缩放
|
|
map: spriteMap,
|
|
depthTest: false,
|
|
transparent: true
|
|
})
|
|
spriteMaterial.name = 'deviceDir'
|
|
Config.spriteMaterialArr.push(spriteMaterial)
|
|
}
|
|
let planeGeometry = new THREE.PlaneGeometry(100, 100)
|
|
let plane = new THREE.Mesh(planeGeometry, spriteMaterial)
|
|
plane.center = new THREE.Vector2(0, 0)
|
|
plane.userData = JSON.parse(JSON.stringify(obj))
|
|
plane.userData.type = 'device'
|
|
plane.position.set(obj.x, -1 * obj.y, 20)
|
|
plane.rotateZ((parseInt(obj.angle) * Math.PI) / 180)
|
|
plane.renderOrder = 410
|
|
_this.devObj.add(plane)
|
|
|
|
let SpriteDiv = document.createElement('div')
|
|
SpriteDiv.className = 'other-pop'
|
|
SpriteDiv.style.background = '#777777'
|
|
SpriteDiv.innerText = obj.devNum
|
|
let pointLabel = new THREE.CSS2DObject(SpriteDiv)
|
|
pointLabel.position.set(obj.x, -1 * obj.y, 0)
|
|
pointLabel.element.style.pointerEvents = 'none'
|
|
pointLabel.userData.type = 'dev_IP'
|
|
pointLabel.userData.code = obj.code
|
|
pointLabel.userData.name = obj.devNum
|
|
_this.showTagObj.add(pointLabel)
|
|
pointLabel.element.style.pointerEvents = 'none'
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 店铺LOGO地图展示类
|
|
*/
|
|
ShopLogo_QM = function () {
|
|
this.renderIcon = function (obj, _this) {
|
|
if (obj) {
|
|
let x = obj.xaxis >> 0
|
|
let y = (-1 * obj.yaxis) >> 0
|
|
let z = parseInt(Config.shopHeight) + 0.1
|
|
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: false,
|
|
transparent: true
|
|
})
|
|
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, z)
|
|
plane.renderOrder = 70
|
|
_this.logoObj.add(plane)
|
|
})
|
|
}
|
|
}
|
|
}
|
|
MySprite_QM.prototype.constructor = MySprite_QM
|
|
|
|
var _selfFindPath
|
|
FindPath_QM = function () {
|
|
this.pathArr = []
|
|
this.lineDashed
|
|
//路线指引箭头皮肤
|
|
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) {
|
|
if (Map_QM.mapArr[Config.selectBuild][Config.selectFloor]) {
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.remove(this.lineDashed)
|
|
}
|
|
this.lineDashed.destroy()
|
|
this.lineDashed = null
|
|
}
|
|
if (Map_QM.guide) {
|
|
Map_QM.guide.visible = false
|
|
if (Map_QM.mapArr[Config.selectBuild][Config.selectFloor]) {
|
|
Map_QM.mapArr[Config.selectBuild][Config.selectFloor].allObj.remove(Map_QM.man_2d)
|
|
Map_QM.mapArr[Config.selectBuild][Config.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 = Config.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 = new PathLine(12, linePath, parseInt(Config.buildHeight) + 1)
|
|
this.lineDashed.name = 'lineDash'
|
|
this.lineDashed.renderOrder = 128
|
|
Map_QM.mapArr[Config.selectBuild][floorOrder].allObj.add(this.lineDashed)
|
|
////////////////////////////////////////////////////////
|
|
}
|
|
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 = Config.shopHeight + 2
|
|
Map_QM.man_3d.position.z = Config.buildHeight + 2
|
|
Map_QM.guide.visible = true
|
|
Map_QM.mapArr[Config.selectBuild][paths.floor].allObj.add(Map_QM.man_2d)
|
|
Map_QM.mapArr[Config.selectBuild][paths.floor].allObj.add(Map_QM.man_3d)
|
|
}
|
|
}
|
|
this.pathArr = paths.PathPoint
|
|
_selfFindPath = this
|
|
if (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 / Config.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 })
|
|
Map_QM.man_3d.rotation.z = Map_QM.man_2d.rotation.z = 0 //180;
|
|
_selfFindPath._index++
|
|
if (_selfFindPath._index > 0 && _selfFindPath._index < _selfFindPath.pathArr.length) {
|
|
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
|
|
}
|
|
}
|
|
for (let t = 0; t < Map_QM.forShopArr[_indexPathFloor].wayShop.length; t++) {
|
|
if (Map_QM.forShopArr[_indexPathFloor].wayShop[t].pathIndex == _selfFindPath._index) {
|
|
pathShop = Map_QM.forShopArr[_indexPathFloor].wayShop[t].shop.houseNumber
|
|
|
|
let shops = Map_QM.mapArr[Config.selectBuild][parseInt(Map_QM.forShopArr[_indexPathFloor].wayShop[t].shop.floorOrder)].allObj.children
|
|
for (let i = 0; i < shops.length; i++) {
|
|
if (shops[i].userData.shopData && shops[i].userData.shopData.houseNumber === pathShop) {
|
|
let shopModel = shops[i]
|
|
let material = shopModel.material
|
|
shopModel.material = new THREE.MeshBasicMaterial({ color: Config.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: { pathArrIn: _indexPathFloor, pathIndex: _selfFindPath._index, 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'
|
|
}
|
|
}
|
|
}
|
|
|