import * as THREE from '@/lib/three/build/three.module.js' import { WEBGL } from '@/lib/three/examples/jsm/WebGL.js' import { OrbitControls } from '@/lib/three/examples/jsm/controls/OrbitControls.js' import { Line2 } from '@/lib/three/examples/jsm/lines/Line2.js' import { LineGeometry } from '@/lib/three/examples/jsm/lines/LineGeometry.js' import { LineMaterial } from '@/lib/three/examples/jsm/lines/LineMaterial.js' import { FBXLoader } from '@/lib/three/examples/jsm/loaders/FBXLoader.js' const EventEmitter = require('events') // var latticeForPiler1 = JSON.parse(JSON.stringify(localStorage.getItem('latticeForPiler1'))) // console.log(this.property.latticeForPiler1); class MapDrawing extends EventEmitter { constructor (container, property) { super() this.initDefaultOptions() this.container = container this.property = this.mergeObject(this.property, property) // this.property.latticeForPiler1=JSON.parse(JSON.stringify(localStorage.getItem('latticeForPiler1'))) } /** * 初始化默认配置 */ initDefaultOptions () { this.property = { width: 500, height: 500, event: { onClick: (data) => { } }, scene: null, camera: null, renderer: null, videoGround: null, light: null, mesh: null, material: { baseLine: null, line: null }, layer: { storageRack: [], storageRackLabel: [], freightSpace: [], fourwayCarRoad: [], roadChild: [], otherPoint: [], pointChild: [], levels: { // nowLevel: localStorage.getItem('level').slice(6, 7) nowLevel:localStorage.getItem('level')?localStorage.getItem('level').slice(6, 7) : 'level-1' } }, textures: [], cars: [], trajectorys: [], errorNodes: {}, raycaster: new THREE.Raycaster(), pointer: new THREE.Vector2(), config: {}, latticeForPiler1 : JSON.parse((localStorage.getItem('latticeForPiler1'))) } let fps = 60 // 多少毫秒执行一次 this.animateControlInfo = { fps: fps, fpsInterval: 1000 / fps, last: new Date().getTime() // 上次执行的时刻 } } /** * 合并json对象 * @param obj1 * @param obj2 * @returns {{}} */ mergeObject (obj1, obj2) { let obj3 = {} for (let attrname in obj1) { if (obj1.hasOwnProperty(attrname)) { obj3[attrname] = obj1[attrname] } } for (let attrname1 in obj2) { if (obj2.hasOwnProperty(attrname1)) { obj3[attrname1] = obj2[attrname1] } } return obj3 } /** * 初始化场景 */ initScene () { this.property.scene = new THREE.Scene() this.property.scene.background = null } /** * 初始化摄像头 */ initCamera () { // 设置透视投影的相机,默认情况下相机的上方向为Y轴,右方向为X轴,沿着Z轴朝里(视野角:fov 纵横比:aspect 相机离视体积最近的距离:near 相机离视体积最远的距离:far) this.property.camera = new THREE.PerspectiveCamera(45, this.property.width / this.property.height, 1, 15000) let eyePoint = this.property.config.eyePoint || [0, 1000, 0] this.property.camera.position.set(eyePoint[0], eyePoint[1], eyePoint[2]) // camera.position.x = 0;//设置相机的位置坐标 // camera.position.y = 0;//设置相机的位置坐标 // camera.position.z = 100;//设置相机的位置坐标 // camera.up.x = 1;//设置相机的上为「x」轴方向 // camera.up.y = 1;//设置相机的上为「y」轴方向 // camera.up.z = 0;//设置相机的上为「z」轴方向 // 设置视野的中心坐标 this.property.camera.lookAt(0, 0, 0) } /** * 初始化渲染器 */ initRender () { this.property.renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true }) // console.log(this.property.width,this.property.height); this.property.renderer.setSize(this.property.width, this.property.height - 180) document.getElementById('mapContainer').appendChild(this.property.renderer.domElement) // 设置背景色 this.property.renderer.setClearColor(0x000000, 1.0) } /** * 初始化事件 */ initEvent () { let self = this document.getElementById('mapContainer').addEventListener('click', (event) => { self.mouseClick(event) }) } /** * 初始化通用材质 */ initMaterials () { // Color:线条的颜色,用16进制来表示,默认的颜色是白色。 // Linewidth:线条的宽度,默认时候1个单位宽度。 // Linecap:线条两端的外观,默认是圆角端点,当线条较粗的时候才看得出效果,如果线条很细,那么你几乎看不出效果了。 // Linejoin:两个线条的连接点处的外观,默认是“round”,表示圆角。 // VertexColors:定义线条材质是否使用顶点颜色,这是一个boolean值。意思是,线条各部分的颜色会根据顶点的颜色来进行插值。 this.property.material.baseLine = new THREE.LineBasicMaterial({ color: 0x0000ff }) this.property.material.line = new LineMaterial({ color: 0x0000ff, linewidth: 5 }) this.property.material.line.resolution.set(this.property.width, this.property.height) this.property.material.colorByPointLine = new THREE.LineBasicMaterial({ vertexColors: THREE.VertexColors }) } /** * 初始化视角交互控制器 */ initControls () { this.property.controls = new OrbitControls(this.property.camera, this.property.renderer.domElement) // controls.addEventListener('change', this.render) // 持续渲染的场景不需要,静态场景才需要监听 // controls.target.set(64, 64, 128) this.property.controls.minZoom = 0.5 this.property.controls.maxZoom = 4 // 限制最大仰视角和俯视角 this.property.controls.minPolarAngle = 0 this.property.controls.maxPolarAngle = 1.5 // 禁止缩放 // controls.enableZoom=false // 缩放限制 // controls.minDistance = 50 // controls.maxDistance = 450 // 是否使用键盘 this.property.controls.enableKeys = true // 修改鼠标按键 this.property.controls.mouseButtons = { LEFT: THREE.MOUSE.PAN, MIDDLE: THREE.MOUSE.DOLLY, RIGHT: THREE.MOUSE.ROTATE } this.property.controls.touches = { ONE: THREE.TOUCH.PAN, // 单个手指 拖动(默认旋转:ROTATE) TWO: THREE.TOUCH.DOLLY_PAN // 两个手指 缩放 } // controls.update() } /** * 初始化光源 */ initLight () { // this.property.light = new THREE.DirectionalLight(0xFF0000, 11.0, 0) // this.property.light.position.set(200, 2000, 200) // this.property.scene.add(this.property.light) this.property.light = new THREE.AmbientLight(0xffffff) this.property.light.position.set(100, 100, 200) this.property.scene.add(this.property.light) // this.property.light = new THREE.PointLight(0xffffff, 1, 0) // this.property.light.position.set(300, 2000, 300) // this.property.scene.add(this.property.light) } layerControl (layerId, showFlg,sliceIndex) { let layer if (layerId.indexOf('level') > -1) { let index = layerId.split('-')[1] layer = this.property.layer.levels[index] if (showFlg) { this.property.layer.levels.nowLevel = sliceIndex } else { this.property.layer.levels.nowLevel = null } } else { layer = this.property.layer[layerId] } if (layerId === 'freightSpace' && Object.keys(this.property.layer.levels).length > 1 && showFlg) { layer = null Object.keys(this.property.layer.levels).map(levelKey => { if (this.property.layer.levels.nowLevel) { layer = this.property.layer.levels[this.property.layer.levels.nowLevel] } }) } if (layer) { layer.map(obj => { if (obj.type === 'GridHelper') { } else if (obj.type === 'Mesh') { obj.visible = showFlg } else if (obj.type === 'Group') { obj.visible = showFlg obj.children.forEach((child, i) => { child.visible = showFlg }) } }) } if (layerId === 'freightSpace') { layer = this.property.layer['storageRackLabel'] layer.map(obj => { if (obj.type === 'GridHelper') { } else if (obj.type === 'Mesh') { obj.visible = !showFlg } else if (obj.type === 'Group') { obj.visible = !showFlg obj.children.forEach((child, i) => { child.visible = !showFlg }) } }) } } /** * 执行渲染 */ render () { this.property.renderer.render(this.property.scene, this.property.camera) } /** * 绘制基础线条 * @param points * @param info * @returns {Line} */ drawBaseLine (points, info, nodeId = '') { let lineMaterial = info ? new THREE.LineBasicMaterial(info) : this.property.material.baseLine var geometry = new THREE.Geometry() points.map((point) => { // 长宽高分别对应桌面的xy以及竖直与屏幕,正值基于000点向右上及屏幕前方延伸 geometry.vertices.push(new THREE.Vector3(point[0], point[1], point[2])) }) var line = new THREE.Line(geometry, lineMaterial) this.property.scene.add(line) line.nodeId = nodeId line.customNodeType = 'baseLine' line.customDataType = info.type || '' line.nodeInfo = info return line } /** * 绘制有宽度的线条 * @param points * @returns {Line2|Line2} */ drawLine (points, info = { id: '' }) { if (!info.id) { info.id = '' } var geometry = new LineGeometry() let pointsBuffer = [] points.map((point) => { // 长宽高分别对应桌面的xy以及竖直与屏幕,正值基于000点向右上及屏幕前方延伸 pointsBuffer.push(point[0]) pointsBuffer.push(point[1]) pointsBuffer.push(point[2]) }) geometry.setPositions(pointsBuffer) var line = new Line2(geometry, this.property.material.line) line.computeLineDistances() this.property.scene.add(line) line.nodeId = info.id line.customNodeType = 'line' line.customDataType = info.type || '' line.nodeInfo = info return line } /** * 画网格 * @param width * @param heigth */ initGrid (width = 1000, heigth = 1000, singleWidth, singleHeight) { singleWidth = singleWidth || 100 singleHeight = singleHeight || 100 let xNum = parseInt(width / singleWidth) let zNum = parseInt(heigth / singleHeight) for (let i = 0; i <= xNum; i++) { let xLine = this.drawBaseLine([[0, 0, -heigth / 2], [0, 0, heigth / 2]], { color: 0xffffff, opacity: 0.1 }) xLine.position.x = (i * width / xNum) - width / 2 } for (let j = 0; j <= zNum; j++) { let zLine = this.drawBaseLine([[-width / 2, 0, 0], [width / 2, 0, 0]], { color: 0xffffff, opacity: 0.1 }) zLine.position.z = (j * heigth / zNum) - heigth / 2 } } /** * 画视频地板 * @param videoDomId * @param height */ initVideoGround () { if (this.property.videoGround) { this.property.videoGround.video = document.createElement(this.property.videoGround.videoDomId) this.property.videoGround.video.src = this.property.videoGround.src this.property.videoGround.video.autoplay = true // this.property.videoGround.video.muted = true this.property.videoGround.video.volume = 0.001 this.property.videoGround.video.loop = true this.property.videoGround.video.load() this.property.videoGround.video.crossOrigin = 'anonymous' // 通过video对象实例化纹理 let texture = new THREE.VideoTexture(this.property.videoGround.video) texture.wrapS = texture.wrapT = THREE.ClampToEdgeWrapping texture.minFilter = THREE.LinearFilter // 创建几何体 let geometry = new THREE.PlaneGeometry(this.property.videoGround.width, this.property.videoGround.height) // 几何体材质对象 const materials = new THREE.MeshBasicMaterial({ map: texture }) // 创建网格模型对象 this.property.videoGround.node = new THREE.Mesh(geometry, materials) // 设置几何体位置 this.property.videoGround.node.position.x = 0 this.property.videoGround.node.position.y = this.property.videoGround.elevation this.property.videoGround.node.position.z = 0 // 设置平躺 this.property.videoGround.node.rotation.x = -Math.PI / 2 this.property.scene.add(this.property.videoGround.node) } } /** * 计算轨迹路线 * @param points * @returns {CurvePath} */ computeCurve (points) { let line, p1, p2, p3 // 作为拐弯的弧度 let R = 20 // 添加一些点作为开头和拐点 let arr = [] points.map(point => { arr.push(new THREE.Vector3(point[0], point[1], point[2])) }) let curvePath = new THREE.CurvePath() for (let i = 0; i < arr.length - 1; i++) { if (i === 0) { let dir = arr[0].clone().sub(arr[1]) dir.normalize() p2 = arr[1].clone() if (arr.length === 2) { p2.add(dir.clone()) } else { p2.add(dir.clone().multiplyScalar(R)) } line = new THREE.LineCurve3(arr[0], p2) curvePath.curves.push(line) } else { // 计算三个点构成的两条线的方向 let dir1 = arr[i - 1].clone().sub(arr[i]) dir1.normalize() let dir2 = arr[i + 1].clone().sub(arr[i]) dir2.normalize() let p12_ = arr[i].clone() p12_.add(dir1.clone().multiplyScalar(R)) p1 = arr[i].clone().add(dir1.clone().multiplyScalar(R)) p2 = arr[i].clone() p3 = arr[i].clone().add(dir2.clone().multiplyScalar(R)) let beziercurve = new THREE.QuadraticBezierCurve3(p1, p2, p3) let line1 = arr[i].clone() line1.add(dir2.clone().multiplyScalar(R)) let line2 = arr[i + 1].clone() if (i < arr.length - 2) { // 最后一段不用减掉半径尺寸 line2.add(dir2.clone().multiplyScalar(-R)) } line = new THREE.LineCurve3(line1, line2) // 把转换曲线和直线插入曲线中 curvePath.curves.push(beziercurve, line) } } return curvePath } /** * 绘制流动管线 * @param curve * @param imageName * @returns {{tube: Mesh, curve: *}} */ createTube (curve, imageName = 'arrow', info) { if (!info.id) { info.id = '' } let width = info.width || 5 let tubeGeometry = new THREE.TubeGeometry(curve, 200, width, 6, false) let textureLoader = new THREE.TextureLoader() let texture = textureLoader.load(require('../../assets/image/' + imageName + '.png')) this.property.textures[info.id] = { texture: texture } texture.wrapS = THREE.RepeatWrapping texture.wrapT = THREE.RepeatWrapping texture.repeat.x = 10 texture.repeat.y = 4 texture.offset.y = 0.5 let tubeMaterial = new THREE.MeshMatcapMaterial({ map: texture, transparent: true }) let tube = new THREE.Mesh(tubeGeometry, tubeMaterial) this.property.scene.add(tube) tube.nodeId = info.id tube.customNodeType = 'pipeline' tube.customDataType = (info.type || '') + 'Trajectory' tube.nodeInfo = info return { curve: curve, tube: tube } } /** * 绘制管线 */ drawPipeline (pathPoints, imageName = 'arrow', info) { return this.createTube(this.computeCurve(pathPoints), imageName, info) } /** * 绘制矩形 * @param info * @returns {Mesh} */ //3.14 drawRectangle (info) { let self = this if (!info.id) { info.id = '' } let defaultInfo = { s3: [20, 20, 20], segments: [1, 1, 1], color: 0x666666 } if (!info) { info = defaultInfo } else { if (!info.s3) { info.s3 = defaultInfo.s3 } if (!info.segments) { info.segments = defaultInfo.segments } if (!info.color) { info.color = defaultInfo.color } if (isNaN(parseFloat(info.rotationX))) { info.rotationX = -Math.PI / 2 } } //构建几何体 let gube = new THREE.CubeGeometry(info.s3[0], info.s3[1], info.s3[2], info.segments[0], info.segments[1], info.segments[2]) // console.log(info.s3[0], info.s3[1], info.s3[2], info.segments[0], info.segments[1], info.segments[2]); var gubeMaterial = new THREE.MeshMatcapMaterial({ color: self.loadColor(info.color) }) var gubeMesh = new THREE.Mesh(gube, gubeMaterial) // gubeMesh.position.set(info.p3[0], info.p3[1], info.p3[2]) gubeMesh.nodeId = info.id gubeMesh.customNodeType = 'rectangle' gubeMesh.customDataType = info.type || '' gubeMesh.nodeInfo = info const group = new THREE.Group() group.position.set(info.p3[0], info.p3[1], info.p3[2]) group.add(gubeMesh) if (info.label) { let label = this.addTextGeometry({ id: info.id, type: info.type + 'Label', label: info.label }) group.add(label) if (info.isStorageRack) { label.visible = false self.property.layer.storageRackLabel.push(label) } if (info.isRoad) { label.visible = false } if (info.isOtherPoint) { label.visible = false } } this.property.scene.add(group) return group } /** * 创建矩形 * @param info * @returns {Mesh} */ createRectangle (info) { // console.log('我执行了'); let self = this if (!info.id) { info.id = '' } let defaultInfo = { s3: [20, 20, 20], segments: [1, 1, 1], color: 0x666666 } if (!info) { info = defaultInfo } else { if (!info.s3) { info.s3 = defaultInfo.s3 } if (!info.segments) { info.segments = defaultInfo.segments } if (!info.color) { info.color = defaultInfo.color } } let gube = new THREE.CubeGeometry(info.s3[0], info.s3[1], info.s3[2], info.segments[0], info.segments[1], info.segments[2]) var gubeMaterial = new THREE.MeshMatcapMaterial({ color: self.loadColor(info.color) }) var gubeMesh = new THREE.Mesh(gube, gubeMaterial) gubeMesh.position.set(info.p3[0], info.p3[1], info.p3[2]) gubeMesh.nodeId = info.id gubeMesh.customNodeType = 'rectangle' gubeMesh.customDataType = info.type || '' gubeMesh.nodeInfo = info return gubeMesh } /** * 创建矩形 * @param info * @returns {Mesh} */ addTextGeometry (info) { // console.log(1111); // debugger if (typeof info === 'string') { info = { id: '', label: info } } let text = info.label if (typeof text !== 'string') { text = text.toString() } let rows = text.split('\r\n') if (!info.lineHeight) { info.lineHeight = 140 } if (!info.scale) { info.scale = 0.6 } if (!info.width) { info.width = 160 } if (!info.height) { info.height = 20 * rows.length + 70 } if (isNaN(parseFloat(info.rotationX))) { info.rotationX = -Math.PI / 2 } // 用canvas生成图片 let canvas = document.createElement('canvas') let ctx = canvas.getContext('2d') canvas.width = info.width canvas.height = info.height // 设置文字 ctx.fillStyle = 'transparent' ctx.fillRect(0, 0, info.width, info.height) rows.map((row, index) => { // if(latticeForPiler1) // 制作矩形 ctx.fillStyle = 'black' ctx.font = '600 40px "宋体"' // ctx.font = '600 40px "宋体"' // ctx.color = 'red' ctx.fillStyle = 'black' ctx.fillText(row, 5, info.lineHeight * index + 60) }) // console.log(ctx); // 生成图片 let url = canvas.toDataURL('image/png') // 将图片构建到纹理中 let geometry1 = new THREE.PlaneGeometry(info.width, info.height) let material1 = new THREE.MeshBasicMaterial({ map: new THREE.TextureLoader().load(url), side: THREE.DoubleSide, opacity: 1, transparent: true }) let rect = new THREE.Mesh(geometry1, material1) rect.position.set(0, 10, 0) rect.rotation.x = info.rotationX if (this.property.config.textRotation) { rect.rotation.z = this.property.config.textRotation } rect.scale.set(info.scale, info.scale, info.scale) rect.nodeId = info.id rect.customNodeType = 'label' rect.customDataType = info.type || '' rect.nodeInfo = info return rect } /** * 绘制内部矩形 * @param paren * @returns {[]} */ drawRactangleInParent (paren, children, dictionary) { let position = paren.node.position let fullHeight = paren.s3[2] * 0.1 > 4 ? paren.s3[2] - 4 : paren.s3[2] * 0.9 let offset = (paren.s3[2] - fullHeight) / 4 let height = (paren.s3[2]) / paren.capacity let y = position.z - paren.s3[2] / 2 + height / 2 + offset let childNodes = [] for (let i = 0; i < children.length; i++) { let child = children[i] let width = paren.s3[0] * 0.1 > 4 ? paren.s3[0] - 4 : paren.s3[0] * 0.9 let stateDictionary = dictionary[dictionary.hasOwnProperty(child.state) ? child.state : '0'] let freightSpace = this.drawRectangle({ id: child.id, parentId: child.parentId, label: child.id, spaceId: child.spaceId, type: paren.childType || 'child', p3: [paren.p3[0], paren.p3[1] + 1, y + height * i], s3: [width, 5, height - 3], segments: [1, 1, 1], state: child.state || 0, color: stateDictionary.color }) childNodes.push(freightSpace) this.property.layer.freightSpace.push(freightSpace) if (this.property.config.mutiLayer) { if (!this.property.layer.levels.hasOwnProperty(child.level)) { this.property.layer.levels[child.level] = [] } this.property.layer.levels[child.level].push(freightSpace) if (child.level > 1) { freightSpace.visible = false } } } return childNodes } /** * 绘制内部矩形(带高度) * @param paren * @returns {[]} */ //四向车当前使用函数 3.15改 drawRactangleInParentWithLevel (paren, children, dictionary) { let childNodes = [] // console.log('我被调用了一次'); for (let i = 0; i < children.length; i++) { let child = children[i] let stateDictionary = dictionary[dictionary.hasOwnProperty(child.state) ? child.state : '0'] // console.log('我被调用了'); let freightSpace = this.drawRectangle({ id: child.id, parentId: child.parentId, label: child.id, spaceId: child.spaceId, type: 'child', p3: [paren.p3[0], paren.p3[1] + 5, paren.p3[2]], s3: [paren.s3[0], 5, paren.s3[2]], segments: [1, 1, 1], state: child.state || 0, color: stateDictionary.color }) childNodes.push(freightSpace) this.property.layer.freightSpace.push(freightSpace) if (this.property.config.mutiLayer) { if (!this.property.layer.levels.hasOwnProperty(child.level)) { this.property.layer.levels[child.level] = [] } this.property.layer.levels[child.level].push(freightSpace) if (child.level > 1) { freightSpace.visible = false } } } return childNodes } /** * 绘制仓库 */ drawWarehouses () { // console.log('我不知道我调用了几次'); //调用一次 let self = this Object.keys(this.property.warehouseInfo.storageRack).map(storageRackId => { let storageRack = this.property.warehouseInfo.storageRack[storageRackId] let stateDictionary = this.property.config.tileStateDictionary[this.property.config.tileStateDictionary.hasOwnProperty(storageRack.state) ? storageRack.state : '0'] //疑似仓库地图 点位`1 console.log(this.property.layer.levels.nowLevel); let storageRackInfo = { id: storageRack.id, type: 'storageRack', label: storageRack.id, p3: [storageRack.x, 0, storageRack.y], // p3: [120, 0, 120], s3: [storageRack.xLength, 2, storageRack.yLength], segments: [1, 1, 1], capacity: storageRack.capacity, color: stateDictionary.color, freightSpace: storageRack.freightSpace, childType: 'freightSpace', state: storageRack.state, isStorageRack: true } storageRackInfo.node = storageRack.node = this.drawRectangle(storageRackInfo) self.property.layer.storageRack.push(storageRackInfo.node) let freightSpaces = Object.values(storageRackInfo.freightSpace) let dictionary = this.property.config.freightSpaceStateDictionary if (self.property.config.mutiLayer) { // console.log('你好,Mr.sun',storageRackInfo); storageRack.childNodes = self.drawRactangleInParentWithLevel(storageRackInfo, freightSpaces, dictionary) } else { console.log(2222); storageRack.childNodes = self.drawRactangleInParent(storageRackInfo, freightSpaces, dictionary) } }) } filterFreightSpace (rowIndex, columnIndex, levelIndex) { this.property.layer.freightSpace.map(freightSpace => { let suc = false freightSpace.children.forEach((child, i) => { if (child.nodeInfo.spaceId) { let nums = child.nodeInfo.spaceId.split('-') if ((isNaN(parseInt(rowIndex)) || rowIndex === nums[0]) && (isNaN(parseInt(columnIndex)) || columnIndex === nums[1]) && (isNaN(parseInt(levelIndex)) || levelIndex === nums[2])) { suc = true } } }) freightSpace.visible = suc }) } /** * 绘制四向车通路 */ drawRoad () { let self = this Object.keys(this.property.warehouseInfo.fourwayCarRoad).map(fourwayCarRoadId => { let fourwayCarRoad = this.property.warehouseInfo.fourwayCarRoad[fourwayCarRoadId] let stateDictionary = this.property.config.roadStateDictionary[this.property.config.roadStateDictionary.hasOwnProperty(fourwayCarRoad.state) ? fourwayCarRoad.state : '0'] //p3 let fourwayCarRoadInfo = { id: fourwayCarRoad.id, type: 'fourwayCarRoad', label: fourwayCarRoad.id, p3: [fourwayCarRoad.x, 0, fourwayCarRoad.y], // p3: [1, 0, 2], s3: [fourwayCarRoad.xLength, 2, fourwayCarRoad.yLength], segments: [1, 1, 1], color: stateDictionary.color, level: fourwayCarRoad.level, childType: 'roadTile', isRoad: true } fourwayCarRoadInfo.node = fourwayCarRoad.node = this.drawRectangle(fourwayCarRoadInfo) self.property.layer.fourwayCarRoad.push(fourwayCarRoadInfo.node) let children = Object.values(fourwayCarRoadInfo.level) let dictionary = this.property.config.roadStateDictionary if (self.property.config.mutiLayer) { fourwayCarRoad.childNodes = self.drawRactangleInParentWithLevel(fourwayCarRoadInfo, children, dictionary) } else { fourwayCarRoad.childNodes = self.drawRactangleInParent(fourwayCarRoadInfo, children, dictionary) } }) } /** * 绘制特殊点位 */ drawOtherPoint () { let self = this Object.keys(this.property.warehouseInfo.otherPoint).map(otherPointId => { let otherPoint = this.property.warehouseInfo.otherPoint[otherPointId] let stateDictionary = this.property.config.otherPointStateDictionary[this.property.config.otherPointStateDictionary.hasOwnProperty(otherPoint.state) ? otherPoint.state : '0'] let otherPointInfo = { id: otherPoint.id, type: 'otherPoint', label: otherPoint.id, p3: [otherPoint.x, 0, otherPoint.y], s3: [otherPoint.xLength, 2, otherPoint.yLength], segments: [1, 1, 1], color: stateDictionary.color, childType: 'otherPointTile', isOtherPoint: true } otherPointInfo.node = otherPoint.node = this.drawRectangle(otherPointInfo) self.property.layer.otherPoint.push(otherPointInfo.node) let children = Object.values(otherPointInfo.level) let dictionary = this.property.config.otherPointStateDictionary if (self.property.config.mutiLayer) { otherPoint.childNodes = self.drawRactangleInParentWithLevel(otherPointInfo, children, dictionary) } else { otherPoint.childNodes = self.drawRactangleInParent(otherPointInfo, children, dictionary) } }) } /** * 绘制堆垛机 */ drawPilers () { if (this.property.warehouseInfo.piler) { Object.keys(this.property.warehouseInfo.piler).map(pilerId => { let piler = this.property.warehouseInfo.piler[pilerId] piler.type = 'piler' piler.p3 = piler.pathPoints[0] piler.segments = [1, 1, 1] let stateDictionary = this.property.config.pilerStateDictionary[this.property.config.pilerStateDictionary.hasOwnProperty(piler.state) ? piler.state : '0'] piler.color = stateDictionary.color piler.node = this.drawRectangle(piler) piler.pathModel = this.drawPipeline(piler.pathPoints, 'arrow', piler) }) } } /** * 绘制小车 */ drawCars () { if (this.property.warehouseInfo.carModel.cars) { Object.keys(this.property.warehouseInfo.carModel.cars).map(carId => { let car = this.property.warehouseInfo.carModel.cars[carId] if (car.pathPoints) { car.type = 'car' car.label = car.id car.p3 = car.pathPoints[0] car.segments = [1, 1, 1] let stateDictionary = this.property.config.carStateDictionary[this.property.config.carStateDictionary.hasOwnProperty(car.state) ? car.state : '0'] car.color = stateDictionary.color car.node = this.drawRectangle(car) } }) } } /** * 绘制小车 */ drawCar (carInfo) { if (!this.property.warehouseInfo.carModel) { this.property.warehouseInfo.carModel = { cars: {} } } if (!this.property.warehouseInfo.carModel.cars.hasOwnProperty(carInfo.carId)) { let car = this.property.warehouseInfo.carModel.cars[carInfo.carId] = JSON.parse(JSON.stringify(carInfo)) car.id = car.carId car.type = 'car' car.label = car.carId car.p3 = car.pathPoints[0] car.segments = [1, 1, 1] let stateDictionary = this.property.config.carStateDictionary[this.property.config.carStateDictionary.hasOwnProperty(car.state) ? car.state : '0'] car.color = stateDictionary.color car.node = this.drawRectangle(car) } } /** * 绘制传送带 */ drawBelt () { if (this.property.warehouseInfo.beltModel) { let beltModel = this.property.warehouseInfo.beltModel if (beltModel.pathPoints) { beltModel.pathModel = this.drawPipeline(beltModel.pathPoints, 'arrow-g', beltModel) Object.keys(this.property.warehouseInfo.beltModel.trays).map(trayId => { let tray = this.property.warehouseInfo.beltModel.trays[trayId] tray.type = 'tray' tray.label = tray.id tray.p3 = beltModel.pathPoints[0] tray.segments = [1, 1, 1] let stateDictionary = this.property.config.trayStateDictionary[this.property.config.trayStateDictionary.hasOwnProperty(tray.state) ? tray.state : '0'] tray.color = stateDictionary.color tray.node = this.drawRectangle(tray) }) } } } getS3 (mesh) { let box = new THREE.Box3().setFromObject(mesh) let size = box.size() return size } /** * 物体是否在场景中显示 * @param {THREE.Object3D} obj 3D物体 * @return {Boolean} 是否在场景中显示 * */ activeInHierarchy (obj) { if (!obj.visible) { return false } // 遍历父对象 let parent = obj.parent while (parent) { if (!parent.visible) { return 0 } parent = parent.parent } return 1 } /** * 获取点击到的所有物体 * @param {THREE.Event} event 点击事件 * @param {THREE.Group} group group * @param {Boolean} visibleType 物体隐藏还是显示 0只看隐藏的1只看显示的2看全部的 * @return {Array} 射线下的所有物体 * */ getIntersects (event, visibleType = 1) { let canvas = event.path ? event.path[0] : event.currentTarget.children[0] event.preventDefault() /** * THREE.Raycaster 对象从屏幕上的点击位置向场景发射的一束光线 * THREE.Raycaster,THREE.Vector2():声明raycaster 和mouse变量 * */ var raycaster = new THREE.Raycaster() // 处理画布与电脑屏幕存在偏移量问题 var divObj = canvas.getBoundingClientRect() // 获取鼠标点击位置 var Sx = event.clientX - divObj.left var Sy = event.clientY - divObj.top // 将鼠标位置归一化为设备坐标。x 和 y 方向的取值范围是 (-1 to +1) var x = (Sx / canvas.width) * 2 - 1 var y = -(Sy / canvas.height) * 2 + 1 // 通过鼠标点击的位置(二维坐标)和当前相机的矩阵计算出射线的位置 raycaster.setFromCamera(new THREE.Vector2(x, y), this.property.camera) // 获取与raycaster射线相交的数组集合,其中的元素按照距离排序,越靠近的越靠前 var intersects = raycaster.intersectObjects(this.property.scene.children, true) let objs = [] intersects.forEach(object => { if (visibleType === 2 || this.activeInHierarchy(object.object) === visibleType) { objs.push(object) } }) // 返回选中的对象数组query return objs } /** * 点击事件 **/ mouseClick (event) { const intersects = this.getIntersects(event) let data = { all: [] } if (intersects.length > 0) { intersects.map(intersect => { let selectObj = intersect.object if (selectObj.hasOwnProperty('customNodeType')) { if (!data[selectObj.customNodeType]) { data[selectObj.customNodeType] = [] } data[selectObj.customNodeType].push(selectObj) data['all'].push(selectObj) } }) } // this.property.event.onClick(data) this.property.event.ondblclick(data) } /** * 动画处理 */ animate (from) { // console.log(1122222); let self = from || this requestAnimationFrame(() => { // console.log(111); self.animate(self) }) // if (!this.interValKey) { // this.interValKey = setInterval(() => { // self.animate(self) // }, 100) // } // 执行时的时间 var now = new Date().getTime() var elapsed = now - this.animateControlInfo.last // console.log(elapsed,this.animateControlInfo.fpsInterval); // 经过了足够的时间 if (elapsed > this.animateControlInfo.fpsInterval) { this.animateControlInfo.last = now - (elapsed % this.animateControlInfo.fpsInterval) // 校正当前时间 if (self.property.warehouseInfo) { self.computePipeLineFlow() if (self.property.warehouseInfo.piler) { self.computePilerState() } if (self.property.warehouseInfo.carModel) { self.computeCarState() } if (self.property.warehouseInfo.beltModel) { self.computeTrayState() } } self.render() } // if (this.property.videoGround && this.property.videoGround.video.played) { // } } moveTo (nodeId, fuzzyQuery = false) { let position = this.getPositionByText(nodeId, fuzzyQuery) if (position) { let nowEyePoint = this.property.camera.position let newEyePoint = [ nowEyePoint.x + position.x - this.property.controls.target.x, nowEyePoint.y + position.y - this.property.controls.target.y, nowEyePoint.z + position.z - this.property.controls.target.z ] let distance = this.getDistanceByPoints(newEyePoint, position) let rate = 500 / distance newEyePoint = this.getNewPointByRate(position, newEyePoint, rate) this.property.camera.position.set(newEyePoint[0], newEyePoint[1], newEyePoint[2]) this.property.controls.target.set(position.x, position.y, position.z) } } getNewPointByRate (p1, p2, rate = 1) { if (p1.x) { if (p1.e) { p1.y = p1.e } p1 = [p1.x, p1.y, p1.z] } if (p2.x) { if (p2.e) { p2.y = p2.e } p2 = [p2.x, p2.y, p2.z] } let newPoint = [ p1[0] + (p2[0] - p1[0]) * rate, p1[1] + (p2[1] - p1[1]) * rate, p1[2] + (p2[2] - p1[2]) * rate ] return newPoint } getDistanceByPoints (p1, p2) { if (p1.x) { if (p1.e) { p1.y = p1.e } p1 = [p1.x, p1.y, p1.z] } if (p2.x) { if (p2.e) { p2.y = p2.e } p2 = [p2.x, p2.y, p2.z] } let distance = Math.sqrt(Math.pow(p2[0] - p1[0], 2) + Math.pow(p2[1] - p1[1], 2) + Math.pow(p2[2] - p1[2], 2)) return distance } getPositionByText (text, fuzzyQuery = false) { let position = null this.property.scene.traverse(obj => { if (obj.type === 'GridHelper') { } else if (obj.type === 'Mesh') { if (obj.nodeId !== undefined && obj.customDataType === 'freightSpace') { if ((!fuzzyQuery && obj.nodeId.toString() === text) || (fuzzyQuery && obj.nodeId.toString().indexOf(text) > -1)) { if (!position || obj.position.x || obj.position.y || obj.position.z) { position = obj.position } } } } else if (obj.type === 'Group') { let exist = false obj.children.forEach((child, i) => { if (child.nodeId !== undefined) { if ((!fuzzyQuery && child.nodeId.toString() === text) || (fuzzyQuery && child.nodeId.toString().indexOf(text) > -1)) { exist = true } } }) if (exist) { position = obj.position } } }) return position } /** * 管线流动 */ computePipeLineFlow () { let self = this Object.keys(self.property.textures).map(textureID => { if (self.property.textures[textureID].direction === -1) { self.property.textures[textureID].texture.offset.x += 0.005 } else { self.property.textures[textureID].texture.offset.x -= 0.005 } }) } /** * 计算堆垛机当前状态 */ computePilerState () { let self = this Object.keys(this.property.warehouseInfo.piler).map((pilerId, index) => { let piler = this.property.warehouseInfo.piler[pilerId] let trajectory = piler.pathModel if (piler.noAnim) { let position = trajectory.curve.getPoint(piler.targetRate / 100) piler.node.position.set(position.x, position.y, position.z) piler.noAnim = false } else { let step = piler.step || 0.1 if (trajectory && piler.targetRate !== null && piler.targetRate !== undefined && piler.rate !== null && piler.rate !== undefined) { if (Math.abs(piler.rate - piler.targetRate) < 0.001) { if (!piler.stopFlg) { piler.stopFlg = true self.stopPiler(piler.id) } } else { if (piler.rate < piler.targetRate) { piler.rate += piler.targetRate - piler.rate > step ? step : piler.targetRate - piler.rate } else if (piler.rate > piler.targetRate) { piler.rate -= piler.rate - piler.targetRate > step ? step : piler.rate - piler.targetRate } let position = trajectory.curve.getPoint(piler.rate / 100) if (position) { piler.node.position.set(position.x, position.y, position.z) position = trajectory.curve.getPoint(piler.rate / 100 + 0.001) if (position) { piler.node.up = new THREE.Vector3(0, 1, 0) piler.node.lookAt(position.x, position.y, position.z) piler.node.rotation.y = piler.node.rotation.y + Math.PI / 2 } } } } } if (piler.state === '3') { if (!piler.scale || piler.scale > 1.5) { piler.scale = 1 } piler.scale = piler.scale + 0.01 piler.node.scale.set(piler.scale, 1, piler.scale) } let stateDictionary = self.property.config.pilerStateDictionary[piler.state] if (stateDictionary) { piler.node.children[0].material.color.set(self.loadColor(stateDictionary.color)) } }) } /** * 计算小车当前状态 */ computeCarState () { let self = this Object.keys(this.property.warehouseInfo.carModel.cars).map((carId, index) => { let car = this.property.warehouseInfo.carModel.cars[carId] let trajectory = car.pathModel if (car.noAnim) { let position = trajectory.curve.getPoint(car.targetRate / 100) car.node.position.set(position.x, position.y, position.z) car.noAnim = false } else { let step = car.step || 0.2 if (trajectory && car.targetRate !== null && car.targetRate !== undefined && car.rate !== null && car.rate !== undefined) { if (Math.abs(car.rate - car.targetRate) < 0.001) { if (!car.stopFlg) { car.stopFlg = true self.stopCar(car.id) } } else { if (car.rate < car.targetRate) { car.rate += car.targetRate - car.rate > step ? step : car.targetRate - car.rate } else if (car.rate > car.targetRate) { car.rate -= car.rate - car.targetRate > step ? step : car.rate - car.targetRate } let position = trajectory.curve.getPoint(car.rate / 100) if (position) { car.node.position.set(position.x, position.y, position.z) position = trajectory.curve.getPoint(car.rate / 100 + 0.001) if (position) { car.node.up = new THREE.Vector3(0, 1, 0) car.node.lookAt(position.x, position.y, position.z) car.node.rotation.y = car.node.rotation.y - Math.PI / 2 } } } } } let stateDictionary = self.property.config.carStateDictionary[car.state] if (stateDictionary) { car.node.children[0].material.color.set(self.loadColor(stateDictionary.color)) } }) } /** * 计算托盘当前状态 */ computeTrayState () { let self = this let trajectory = this.property.warehouseInfo.beltModel.pathModel Object.keys(this.property.warehouseInfo.beltModel.trays).map((trayId, index) => { let tray = this.property.warehouseInfo.beltModel.trays[trayId] if (tray.noAnim) { let position = trajectory.curve.getPoint(tray.targetRate / 100) tray.node.position.set(position.x, position.y, position.z) tray.noAnim = false } else { let step = tray.step || 0.2 if (trajectory && tray.targetRate !== null && tray.targetRate !== undefined && tray.rate !== null && tray.rate !== undefined) { if (Math.abs(tray.rate - tray.targetRate) < 0.001) { if (!tray.stopFlg) { tray.stopFlg = true self.stopTray(tray.id) } } else { if (tray.rate < tray.targetRate) { tray.rate += tray.targetRate - tray.rate > step ? step : tray.targetRate - tray.rate } else if (tray.rate > tray.targetRate) { tray.rate -= tray.rate - tray.targetRate > step ? step : tray.rate - tray.targetRate } let position = trajectory.curve.getPoint(tray.rate / 100) if (position) { tray.node.position.set(position.x, position.y, position.z) position = trajectory.curve.getPoint(tray.rate / 100 + 0.001) if (position) { tray.node.up = new THREE.Vector3(0, 1, 0) tray.node.lookAt(position.x, position.y, position.z) tray.node.rotation.y = tray.node.rotation.y + Math.PI / 2 } } } } } let stateDictionary = self.property.config.trayStateDictionary[tray.state] if (stateDictionary) { tray.node.children[0].material.color.set(self.loadColor(stateDictionary.color)) } }) } /** * 更新堆垛机状态 * @param pilerInfo */ updatePiler (pilerInfo) { let self = this setTimeout(() => { // 因为是事件回调中更新,所以需要setTimeout,不然持续更新错误状态 self.doUpdatePiler(pilerInfo) }, 100) } doUpdatePiler (pilerInfo) { let piler = this.property.warehouseInfo.piler[pilerInfo.pilerId] if (piler) { switch (pilerInfo.carryCargo) { default: case false: if (piler.node.children.length > 2) { piler.node.remove(piler.node.children[2]) } break case true: if (piler.node.children.length <= 2) { let parentS3 = piler.s3 let reckInfo = { id: pilerInfo.cargoId, type: 'cargo', p3: [0, parentS3[1] / 2 + 1, 0], s3: [parentS3[0] / 2 - 2, 1, parentS3[2] - 4], segments: [1, 1, 1], color: 0x333300 } let rect = this.createRectangle(reckInfo) piler.node.add(rect) } break } if (!piler.rate) { piler.rate = 0 } if (pilerInfo.state === '3') { this.property.errorNodes[pilerInfo.pilerId] = pilerInfo.pilerId piler.state = '3' } else { if (this.property.errorNodes.hasOwnProperty(pilerInfo.pilerId)) { delete this.property.errorNodes[pilerInfo.pilerId] } if (pilerInfo.noAnim) { piler.noAnim = pilerInfo.noAnim piler.rate = pilerInfo.rate } else { piler.stopFlg = false } if (pilerInfo.hasOwnProperty('state')) { piler.state = pilerInfo.state } else { if (piler.rate < pilerInfo.rate) { piler.state = '1' } else if (piler.rate > pilerInfo.rate) { piler.state = '2' } else if (piler.rate === pilerInfo.rate) { piler.state = '0' } } } piler.targetRate = pilerInfo.rate let textureLoader = new THREE.TextureLoader() let texture switch (piler.state) { default: case '0': texture = textureLoader.load(require('../../assets/image/arrow.png')) this.property.textures[pilerInfo.pilerId].direction = 1 break case '1': texture = textureLoader.load(require('../../assets/image/arrow-g.png')) this.property.textures[pilerInfo.pilerId].direction = 1 break case '2': texture = textureLoader.load(require('../../assets/image/arrow-r.png')) this.property.textures[pilerInfo.pilerId].direction = -1 break case '3': texture = textureLoader.load(require('../../assets/image/arrow.png')) this.property.textures[pilerInfo.pilerId].direction = 1 break } texture.wrapS = THREE.RepeatWrapping texture.wrapT = THREE.RepeatWrapping texture.repeat.x = 10 texture.repeat.y = 4 texture.offset.y = 0.5 piler.pathModel.tube.material.map = texture this.property.textures[pilerInfo.pilerId].texture = texture } } /** * 停止堆垛机动画触发 * @param pilerId */ stopPiler (pilerId) { let piler = this.property.warehouseInfo.piler[pilerId] if (piler) { if (piler.state !== '3') { piler.state = '0' } let textureLoader = new THREE.TextureLoader() let texture = textureLoader.load(require('../../assets/image/arrow.png')) texture.wrapS = THREE.RepeatWrapping texture.wrapT = THREE.RepeatWrapping texture.repeat.x = 10 texture.repeat.y = 4 texture.offset.y = 0.5 piler.pathModel.tube.material.map = texture this.property.textures[pilerId].texture = texture try { this.property.event.onAnimateStop('piler', piler) } catch (e) { // console.log(e.toString()) } } } /** * 更新小车位置 * @param carInfo */ updateCar (carInfo) { let self = this setTimeout(() => { // 因为是事件回调中更新,所以需要setTimeout,不然持续更新错误状态 self.doUpdateCar(carInfo) }, 100) } doUpdateCar (carInfo) { let car = this.property.warehouseInfo.carModel.cars[carInfo.carId] if (car) { if (carInfo.pathPoints) { car.rate = 0 car.pathModel = this.drawPipeline(carInfo.pathPoints, 'arrow-g', car) } switch (carInfo.carryCargo) { default: case false: if (car.node.children.length > 2) { car.node.remove(car.node.children[2]) } break case true: if (car.node.children.length <= 2) { let parentS3 = car.s3 let reckInfo = { id: carInfo.cargoId, type: 'cargo', p3: [0, 2, 0], s3: [parentS3[0] - 4, 20, parentS3[2] - 4], segments: [1, 1, 1], color: 0x333300 } let rect = this.createRectangle(reckInfo) car.node.add(rect) } break } if (!car.rate) { car.rate = 0 } car.targetRate = carInfo.rate if (carInfo.noAnim) { car.noAnim = carInfo.noAnim car.rate = car.targetRate } else { car.stopFlg = false } if (carInfo.hasOwnProperty('state')) { car.state = carInfo.state } else { car.state = car.rate !== carInfo.rate ? '1' : '0' } } } /** * 停止小车动画触发 * @param carId */ stopCar (carId) { let car = this.property.warehouseInfo.carModel.cars[carId] if (car) { if (car.pathModel && car.pathModel.tube) { this.property.scene.remove(car.pathModel.tube) } car.state = '0' try { this.property.event.onAnimateStop('car', car) } catch (e) { // console.log(e.toString()) } } } /** * 修改托盘位置 * @param trayInfo */ updateTray (trayInfo) { let self = this setTimeout(() => { // 因为是事件回调中更新,所以需要setTimeout,不然持续更新错误状态 self.doUpdateTray(trayInfo) }, 100) } doUpdateTray (trayInfo) { let tray = this.property.warehouseInfo.beltModel.trays[trayInfo.trayId] if (tray) { switch (trayInfo.carryCargo) { default: case false: if (tray.node.children.length > 2) { tray.node.remove(tray.node.children[2]) } break case true: if (tray.node.children.length <= 2) { let parentS3 = tray.s3 let reckInfo = { id: trayInfo.cargoId, type: 'cargo', p3: [0, 2, 0], s3: [parentS3[0] - 4, 20, parentS3[2] - 4], segments: [1, 1, 1], color: 0x333300 } let rect = this.createRectangle(reckInfo) tray.node.add(rect) } break } if (!tray.rate) { tray.rate = 0 } tray.targetRate = trayInfo.rate if (trayInfo.noAnim) { tray.noAnim = trayInfo.noAnim tray.rate = tray.targetRate } else { tray.stopFlg = false } if (trayInfo.hasOwnProperty('state')) { tray.state = trayInfo.state } else { tray.state = tray.rate !== trayInfo.rate ? '1' : '0' } } } /** * 停止托盘动画触发 * @param trayId */ stopTray (trayId) { let tray = this.property.warehouseInfo.beltModel.trays[trayId] if (tray) { tray.state = '0' try { this.property.event.onAnimateStop('tray', tray) } catch (e) { // console.log(e.toString()) } } } /** * 更新仓库库存状态 */ updateStorage (warehouseInfo) { let self = this let warehouseData = JSON.parse(JSON.stringify(warehouseInfo)) let freightSpaceStateDictionary = JSON.parse(JSON.stringify(this.property.config.freightSpaceStateDictionary)) Object.keys(warehouseData.storageRack).map(storageRackId => { Object.keys(warehouseData.storageRack[storageRackId].freightSpace).map(freightSpaceId => { let freightSpace = warehouseData.storageRack[storageRackId].freightSpace[freightSpaceId] Object.keys(freightSpaceStateDictionary).map(tileStateKey => { if (freightSpace.state&&freightSpace.state.toString() === tileStateKey) { if (!freightSpaceStateDictionary[tileStateKey].nodeIds) { freightSpaceStateDictionary[tileStateKey].nodeIds = [] } freightSpaceStateDictionary[tileStateKey].nodeIds.push(freightSpace.id) } }) }) }) this.property.scene.traverse(obj => { if (obj.type === 'GridHelper') { } else if (obj.type === 'Mesh') { if (obj.customDataType === 'freightSpace') { Object.keys(freightSpaceStateDictionary).map(tileStateKey => { if (freightSpaceStateDictionary[tileStateKey].nodeIds && freightSpaceStateDictionary[tileStateKey].nodeIds.indexOf(obj.nodeId) > -1) { obj.material.color.set(self.loadColor(freightSpaceStateDictionary[tileStateKey].color)) } }) } } else if (obj.type === 'Group') { obj.children.forEach((child, i) => { Object.keys(freightSpaceStateDictionary).map(tileStateKey => { if (freightSpaceStateDictionary[tileStateKey].nodeIds && freightSpaceStateDictionary[tileStateKey].nodeIds.indexOf(child.nodeId) > -1) { // debugger child.material.color.set(self.loadColor(freightSpaceStateDictionary[tileStateKey].color)) } }) }) } }) } /** * 更新仓库库存状态 */ updateStorageByKey (freightSpaceId, state) { let self = this let tileState = JSON.parse(JSON.stringify(this.property.config.freightSpaceStateDictionary[state])) this.property.scene.traverse(obj => { if (obj.type === 'GridHelper') { } else if (obj.type === 'Mesh') { if (obj.nodeId !== undefined && obj.nodeId.toString() === freightSpaceId) { obj.material.color.set(self.loadColor(tileState.color)) } } else if (obj.type === 'Group') { obj.children.forEach((child, i) => { if (child.nodeId !== undefined && child.nodeId.toString() === freightSpaceId) { child.material.color.set(self.loadColor(tileState.color)) } }) } }) } loadColor (colorText) { if (typeof colorText === 'string') { let color = parseInt(colorText.replace(/#/g, '0x')) // let color = parseInt(colorText.replace(/#/g, '0x')) // console.log(colorText); return color } else { return colorText } } loadFbxModel (url) { let self = this // 实例化一个FBXLoader对象 const loader = new FBXLoader() // 加载fbx文件 loader.load(url, (model) => { model.traverse(childModel => { self.loadColorForModel(childModel) }) // 将模型添加到场景中 self.property.scene.add(model) }, (event) => { // 控制台打印加载进度 // console.log((event.loaded / event.total * 100) + '% loaded') }, (error) => { // 控制台打印加载失败 console.error(error) }) } loadColorForModel (model) { let self = this if (model.material) { model.castShadow = true model.material.emissive = model.material.color model.material.emissiveMap = model.material.map } else if (model.children.length > 0) { model.children.map(childModel => { self.loadColorForModel(childModel) }) } } /** * 初始化地图 */ initMap () { if (WEBGL.isWebGLAvailable() === false) { document.body.appendChild(WEBGL.getWebGLErrorMessage()) } else { this.initScene() this.initCamera() this.initRender() this.initMaterials() this.initControls() // this.initVideoGround() } } initWarehouse () { if (this.property.warehouseInfo) { this.drawWarehouses() if (this.property.config.vehicleType === 1) { // this.drawPilers() // this.drawBelt() } else { this.drawRoad() } // this.drawCars() } else { this.initLight() } this.animate() this.initEvent() // if (this.property.grid) { // this.initGrid(this.property.grid.width, this.property.grid.height, this.property.grid.singleWidth, this.property.grid.singleHeight) // } } } export default MapDrawing