<script src="../../api/smartTraffic.js"></script> <template> <div style="width: 100%; height:100%"> <div style="width:100%; height:100%;position:relative"> <div style="position:absolute;top:40px;left:50px;z-index:100000"> <div style="margin-left: 1em"> <img :src="require('@/assets/images/button/up.png')" style="width: 250px"/> </div> <div v-for="(value,key,index) in labels" :key="index"> <button2 v-model="layersShow[key]" @click.native="clickLabel(key)" :data="labels[key]" @fetchData="fetchData">{{value.name}}</button2><br/> </div> <img :src="require('@/assets/images/button/down.png')" style="margin-left: 1em;padding-bottom: 1em;width: 250px"/> </div> <div id="mars3dContainer" class="mars3d-container"/> </div> </div> </template> <script> // 在需要用到mars3d的vue等页面直接引入并使用 import * as mars3d from 'mars3d' import * as mapv from 'mapv' import 'mars3d/dist/mars3d.css' import 'mars3d-heatmap/dist/mars3d-heatmap.js' import Button2 from '@/components/button/button2' import {fetchCarInfo, fetchFeatureInfo, fetchCarPostion} from '@/api/map' import {fetchBlockPoints, fetchEventPoints} from '@/api/smartTraffic' import { dateToString, getLastWeek } from '@/utils/formatDate' import 'cesium/Source/Widgets/widgets.css'// 导入必须的样式表 var Cesium = require('../../../node_modules/cesium/Source/Cesium') export default { name: 'Mars3dMap', components: {Button2}, data () { return { top: '250px', layersShow: [false, false, false, false, false, false, false, false], labels: [ { index: '01', name: '人口分布', children: ['区域人口统计', '网格人口统计', '楼栋人口统计'], layersShow: [false, false, false]}, { index: '02', name: '物联网', children: [ '电子标识器', '液位监测仪', '消防栓防盗水监测仪', '有害气体监测仪', '井盖状态监测仪', '噪声记录仪', '燃气智能监测终端', '数据集中器', '电警', '卡口', 'AR鹰眼', '智慧社区', '智慧教育', '智慧工地', '公安视频', '路灯', '环监'], layersShow: [false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false]}, { index: '03', name: '事件分布', children: ['城管执法案件', '综治案件', '社区案件'], layersShow: [false, false] }, { index: '04', name: '场所分布', children: ['社区分布', '企业分布', '个体户分布', '建筑业企业分布', '停车场分布', '工地分布', '公园分布'], layersShow: [false, false, false, false, false, false, false] }, { index: '05', name: '网格分布', children: ['疫情网格', '综治网格'], layersShow: [false, false] }, { index: '06', name: '智慧交通', children: ['拥堵点分布', '交通事件分布', '高发事故点分布'], layersShow: [false, false, false] }, { index: '07', name: '项目分布', children: [], layersShow: [] }, { index: '08', name: '车辆信息', children: ['渣土车分布', '渣土车轨迹'], layersShow: [false, false] } ], data: { feature: [], polygon: [] }, layers: { heatLayer: null, feature: '', polygon: '' }, map: '', cartimer: null } }, mounted () { let _this = this window.trail = _this.trail this.initmap() }, methods: { clickLabel (val) { this.layersShow = [false, false, false, false, false, false, false, false] this.layersShow[val] = true for (let i = 0; i < this.labels.length; i++) { if (i !== val) { for (let j = 0; j < this.labels[i].layersShow.length; j++) { this.labels[i].layersShow[j] = false } } } if (val === 6) { this.fetchData({value: '项目分布'}) } }, initmap () { var mapOptions = { scene: { // 默认视角参数 center: { lat: 25.823284, lng: 114.907684, alt: 2008, heading: 360, pitch: -31 }, // 以下是Cesium.Globe对象相关参数 globe: { depthTestAgainstTerrain: false, // 是否启用深度监测 baseColor: '#00192f', // 地球默认背景色 showGroundAtmosphere: true, // 是否在地球上绘制的地面大气 enableLighting: false // 是否显示昼夜区域 } // 以下是Cesium.ScreenSpaceCameraController对象相关参数 // cameraController: { // zoomFactor: 3.0, // 鼠标滚轮放大的步长参数 // minimumZoomDistance: 1, // 地球放大的最小值(以米为单位) // maximumZoomDistance: 50000000, // 地球缩小的最大值(以米为单位) // enableRotate: true, // 2D和3D视图下,是否允许用户旋转相机 // enableTranslate: true, // 2D和哥伦布视图下,是否允许用户平移地图 // enableTilt: true, // 3D和哥伦布视图下,是否允许用户倾斜相机 // enableZoom: true, // 是否允许 用户放大和缩小视图 // enableCollisionDetection: true // 是否允许 地形相机的碰撞检测 // } }, basemaps: [ { crs: 'gcj', enablePickFeatures: false, icon: 'http://mars3d.cn/example/img/basemaps/bd-c-midnight.png', id: 2017, name: '蓝色底图(GCJ02偏移)', type: 'arcgis', url: 'http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer' } ], layers: [ { name: '行政区划界线', type: 'xyz', url: 'https://t{s}.tianditu.gov.cn/DataServer?T=ibo_w&x={x}&y={y}&l={z}&tk=9ae78c51a0a28f06444d541148496e36', subdomains: '01234567', maximumLevel: 10, show: true, id: 1, templateValues: { dataServer: 'http://data.marsgis.cn' }, zIndex: 0 }, { name: '天地图注记', type: 'tdt', layer: 'img_z', key: [ '9ae78c51a0a28f06444d541148496e36' ], show: false, id: 2, templateValues: { dataServer: 'http://data.marsgis.cn' }, zIndex: 1 } ] } // 创建三维地球场景 var map = new mars3d.Map('mars3dContainer', mapOptions) map.basemap = 2017 map.scene.screenSpaceCameraController.enableCollisionDetection = false // 设置鼠标 map.scene.screenSpaceCameraController.tiltEventTypes = [ Cesium.CameraEventType.RIGHT_DRAG ] // 缩放设置 重新设置缩放成员 map.scene.screenSpaceCameraController.zoomEventTypes = [Cesium.CameraEventType.MIDDLE_DRAG, Cesium.CameraEventType.WHEEL, Cesium.CameraEventType.PINCH] // 鼠标左键平移 map.scene.screenSpaceCameraController.rotateEventTypes = [Cesium.CameraEventType.LEFT_DRAG] this.map = map // 加动态图层 this.layers.feature = new mars3d.layer.GraphicLayer() this.layers.polygon = new mars3d.layer.GraphicLayer() map.addLayer(this.layers.feature) map.addLayer(this.layers.polygon) }, async getCar () { this.layers.polygon.clear() fetchCarInfo().then(response => { if (response.code === 200) { this.data.feature = response.data this.layers.feature.clear() for (let i = 0; i < this.data.feature.length; i++) { var graphic = new mars3d.graphic.ModelEntity({ name: this.data.feature[i].simcardnum, position: [Number(this.data.feature[i].coordinatex), Number(this.data.feature[i].coordinatey)], style: { url: '../static/model/zhatuchelvse.gltf', scale: 10, minimumPixelSize: 40, label: { text: this.data.feature[i].vehiclenum, font_size: 18, color: '#ffffff', pixelOffsetY: -50, distanceDisplayCondition: true, distanceDisplayCondition_far: 500000, distanceDisplayCondition_near: 1000 } } }) var items = [{name: '车牌号', value: 'vehiclenum'}, {name: '公司', value: 'name'}] var str = ` <div style="font-size: 0.082rem;width:30em;padding: 2em;"> <div style="font-size: 0.085rem;font-weight: bold;padding-bottom: 10px;color: #00b3eb">渣土车分布</div>` for (let j in items) { var item = this.data.feature[i][items[j].value] if (typeof item === 'undefined') item = '' str += ` <div style="padding-bottom: 2px"><label style="padding-right: 5px">${items[j].name}:</label>${item}</div>` } var simcardnum = '\'' + this.data.feature[i].simcardnum + '!' + this.data.feature[i].vehiclenum + '\'' // var vehiclenum = this.data.feature[i].vehiclenum str += `<button style="background-color: #e6a23c;border-color: #e6a23c;color: white;padding: 5px 15px;border-radius: 4px;margin-left: 25em" id="btntrail" onclick="trail(${simcardnum})">轨 迹</button>` str += `</div>` debugger graphic.bindPopup(str) this.layers.feature.addGraphic(graphic) } } }) }, trail: function (str) { var val = str.split('!') console.log(val) this.map.closePopup() const now = dateToString(new Date(), 'y-m-d-h-m-s') const cthour = new Date() cthour.setTime(cthour.getTime() - 3599 * 1000) const hour = dateToString(cthour, 'y-m-d-h-m-s') const params = { params: [val[0], hour, now] } fetchCarPostion(params).then(response => { if (response.code === 200) { if (response.data.length !== 0) { var data = response.data.map(item => { return [item.coordinateX, item.coordinateY, 0] }) var flydata = { name: '贴地表表面漫游', speed: 300, positions: data, model: { url: '../static/model/zhatuchelvse.gltf', heading: 180, minimumPixelSize: 50, show: true }, label: { text: val[1], font_size: 18, color: '#ffffff', pixelOffsetY: -50, show: true }, path: { color: '#32c3ff', width: 3, show: true }, camera: { type: 'gs', pitch: -30, radius: 5000 }, interpolation: true, // 是否setInterpolationOptions插值 clockLoop: false // 是否循环播放 } var roamLine = new mars3d.graphic.RoamLine(flydata) this.layers.feature.addGraphic(roamLine) roamLine.start() } } }) }, fetchData ({value}) { this.layers.feature.clear() this.layers.polygon.clear() if (this.layers.heatLayer) { this.map.removeLayer(this.layers.heatLayer, true) } clearInterval(this.cartimer) if (value === '渣土车分布') { var that = this this.getCar() this.cartimer = setInterval(function () { that.getCar() }, 100000000) } else if (value === '电子标识器') { this.singleSearch(value, 'B-ZH-0101', '3KNOXR30E6', require('@/assets/images/icon-camera-blu.png'), [ {name: '标识器ID号', value: 'SJBH'}, {name: '标识器型号', value: 'SBXH'}, {name: '所属道路', value: 'SSSJFW'} ]) } else if (value === '液位监测仪') { this.singleSearch(value, 'B-ZH-0104', 'M1KOD38358', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '消防栓防盗水监测仪') { this.singleSearch(value, 'B-ZH-0107', 'IVU59JC84I', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '有害气体监测仪') { this.singleSearch(value, 'B-ZH-0109', 'VB5P0VER2I', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '井盖状态监测仪') { this.singleSearch(value, 'B-ZH-0103', 'A376X56055', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '噪声记录仪') { this.singleSearch(value, 'B-ZH-0106', '1Y059A446T', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '燃气智能监测终端') { this.singleSearch(value, 'B-ZH-0108', '556018Q5T0', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '数据集中器') { this.singleSearch(value, 'B-ZH-0110', 'RGW6U23D5A', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '路灯') { this.singleSearch(value, 'B-ZH-0403', 'G2YQEM396G', require('@/assets/images/icon-camera-blu.png'), [ {name: '路灯编号', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '环监') { this.singleSearch(value, 'B-ZH-0706', 'JFK37I1F45', require('@/assets/images/icon-camera-blu.png'), [ {name: '设备名称', value: 'YSMC'}, {name: '设备地点', value: 'S_DZQC'} ]) } else if (value === '城管执法案件') { this.singleSearch(value, 'B-ZH-0402', '4X137UY07J', require('@/assets/images/icon-camera-blu.png'), [ {name: '案件名称', value: 'YSMC'}, {name: '案件分类', value: 'XXDLXMC'}, {name: '案件详情', value: 'S_DZQC'} ]) } else if (value === '社区分布') { this.singleSearch(value, 'B-ZH-1001', 'J765870KFV', require('@/assets/images/icon-camera-blu.png'), [ {name: '社区名称', value: 'SSSJFW'}, {name: '社区地址', value: 'S_DZQC'} ]) this.drawPolygon('B-ZH-1004', 'VM0V81395N') } // else if (value === '学校分布') { // this.singleSearch(value, 'B-ZH-0520', '988C6OY8T3', require('@/assets/images/icon-camera-blu.png'), // [ {name: '学校名称', value: 'SSSJFW'}, {name: '学校地址', value: 'S_DZQC'} ]) // this.drawPolygon('B-ZH-0516', '2TFD2VO00Q') // } else if (value === '停车场分布') { this.singleSearch(value, 'B-ZH-1701', '521355523B', require('@/assets/images/icon-camera-blu.png'), [ {name: '停车场名称', value: 'SSSJFW'}, {name: '停车场地址', value: 'S_DZQC'} ]) this.drawPolygon('B-ZH-1702', 'VM0V81395N') } else if (value === '工地分布') { this.singleSearch(value, 'B-ZH-0801', '05VA87X3PX', require('@/assets/images/icon-camera-blu.png'), [{name: '工地名称', value: 'SSSJFW'}, {name: '工程类别', value: 'GCLB'}, {name: '工程状态', value: 'JSJD'}, {name: '开工日期', value: 'GXSJ'}, {name: '项目地址', value: 'S_DZQC'}]) this.drawPolygon('B-ZH-0702', '2V026Q9MNX') } else if (value === '公园分布') { this.singleSearch(value, 'B-ZH-0901', '604NVD1231', require('@/assets/images/icon-camera-blu.png'), [ {name: '公园名称', value: 'SSSJFW'}, {name: '公园地址', value: 'S_DZQC'} ]) this.drawPolygon('B-ZH-0928', '5CAQF6UY5V') } else if (value === '企业分布') { this.singleSearch(value, 'C-QY-001', '4E31K4B9MP', require('@/assets/images/icon-camera-blu.png'), [ {name: '企业名称', value: 'QYMC'}, {name: '企业类型', value: 'QYLX'}, {name: '行业门类', value: 'XYML'}, {name: '企业状态', value: 'QYZT'}, {name: '成立日期', value: 'CLRQ'}, {name: '联系电话', value: 'YDDH'}, {name: '法定代表人', value: 'FDDBR'}, {name: '法定联系电话', value: 'FDDBRLXDH'}, {name: '经营场所', value: 'ZS'}, {name: '统一社会信用代码', value: 'TYSHXYDM'}, {name: '一般经营项目', value: 'YBJYXM'} ]) } else if (value === '个体户分布') { this.singleSearch(value, 'C-GT-001', '3A11W9ONRM', require('@/assets/images/icon-camera-blu.png'), [ {name: '字号名称', value: 'ZHMC'}, {name: '行业门类', value: 'XYML'}, {name: '个体状态', value: 'QYZT'}, {name: '成立日期', value: 'CLRQ'}, {name: '法定代表人', value: 'FDDBR'}, {name: '法定联系电话', value: 'FDDBRLXDH'}, {name: '经营者证件名称', value: 'JYZZJMC'}, {name: '经营者证件号码', value: 'JYZZJHM'}, {name: '经营场所', value: 'ZS'}, {name: '许可经营项目', value: 'XKJYXM'} ]) } else if (value === '建筑业企业分布') { this.singleSearch(value, 'C-QY-002', '5ZW9421ZVZ', require('@/assets/images/icon-camera-blu.png'), [ {name: '企业名称', value: 'QYMC'}, {name: '所属行业', value: 'SSHY'}, {name: '备注施工单位/监理单位', value: 'BZSGDWHSJLDW'}, {name: '建设项目名称', value: 'JSXMMC'}, {name: '法定代表人', value: 'SSSJFW'}, {name: '法定联系电话', value: 'FDDBRLXDH'}, {name: '企业地址', value: 'ZS'}, {name: '统一社会信用代码', value: 'TYSHXYDM'} ]) } else if (value === '项目分布') { this.singleSearch('项目分布', 'B-ZH-0801', '05VA87X3PX', require('@/assets/images/icon-camera-blu.png'), [{name: '项目名称', value: 'SSSJFW'}, {name: '项目类别', value: 'GCLB'}, {name: '项目状态', value: 'JSJD'}, {name: '开工日期', value: 'GXSJ'}, {name: '项目地址', value: 'S_DZQC'}]) this.drawPolygon('B-ZH-0702', '2V026Q9MNX') } else if (value === '疫情网格') { this.drawGeoServer() } else if (value === '拥堵点分布') { this.getBlockPoints() } else if (value === '交通事件分布') { this.getEventPoints() } }, async singleSearch (value, code, key, icon, items) { fetchFeatureInfo(code, key).then(response => { this.data.feature = response.data.data[0].data for (let i = 0; i < this.data.feature.length; i++) { var graphic = new mars3d.graphic.BillboardEntity({ name: value, position: [Number(this.data.feature[i].X), Number(this.data.feature[i].Y)], style: { image: icon, scale: 1, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, clampToGround: true } }) var str = ` <div style="font-size: 0.082rem;width:30em;padding: 2em;"> <div style="font-size: 0.085rem;font-weight: bold;padding-bottom: 10px;color: #00b3eb">${value}</div>` for (let j in items) { var item = this.data.feature[i][items[j].value] if (typeof item === 'undefined') item = '' str += ` <div style="padding-bottom: 2px"><label style="padding-right: 5px">${items[j].name}:</label>${item}</div>` } str += `</div>` graphic.bindPopup(str) this.layers.feature.addGraphic(graphic) } }) }, async drawPolygon (code, key) { fetchFeatureInfo(code, key).then(response => { this.data.polygon = response.data.data[0].data for (let i = 0; i < this.data.polygon.length; i++) { // this.data.polygon.length var items = [] var str = this.data.polygon[i].GEO if (str.startsWith('POLYGON')) { str = str.substr(str.indexOf('(') + 2) str = str.substr(0, str.length - 2) items = str.split(',') items = items.map(item => { return item.substr(1).split(' ') }) let graphic = new mars3d.graphic.PolygonEntity({ positions: items, style: { color: '#bebebe', opacity: 0.5, outline: true, outlineWidth: 2, outlineColor: '#46617b' } }) this.layers.polygon.addGraphic(graphic) } else if (str.startsWith('MULTIPOLYGON')) { str = str.substr(str.indexOf('(') + 2) str = str.substr(0, str.length - 2) var list = str.split('),(') for (let j = 0; j < list.length; j++) { list[j] = list[j].substr(1, list[j].length - 2) items = list[j].split(',') items = items.map(item => { return item.substr(1).split(' ') }) let graphic = new mars3d.graphic.PolygonEntity({ positions: items, style: { color: '#bebebe', opacity: 0.5, outline: true, outlineWidth: 2, outlineColor: '#46617b' } }) this.layers.polygon.addGraphic(graphic) } } } }) }, async getBlockPoints () { const today = dateToString(new Date(), 'y-m-d') const sevenday = dateToString(getLastWeek(), 'y-m-d') const params = {params: [sevenday, today]} fetchBlockPoints(params).then(response => { if (response.code === 200) { this.data.feature = response.data var list = this.data.feature.map(item => { let str = item.point.substr(item.point.indexOf('(') + 1) str = str.substr(0, str.length - 1) var items = str.split(' ') return { lng: parseFloat(items[0]), lat: parseFloat(items[1]), value: Number(item.speed) } }) console.log(list) this.layers.heatLayer = new mars3d.layer.HeatLayer({ positions: list, heatStyle: { radius: 170, blur: 0.85 }, style: { opacity: 1.0, clampToGround: true }, redrawZoom: true, flyTo: true }) this.map.addLayer(this.layers.heatLayer) } }) }, async getEventPoints () { var style = { width: 15, material: mars3d.MaterialUtil.createMaterialProperty(mars3d.MaterialType.LineFlow, { color: '#ff3426', repeat: new Cesium.Cartesian2(20, 1), image: '../static/image/line.png', speed: 25 }) } fetchEventPoints().then(response => { if (response.code === 200) { this.data.feature = response.data for (let i = 0; i < this.data.feature.length; i++) { let items = this.data.feature[i].lines.split(';') items = items.map(item => { return item.split(',') }) var graphic = new mars3d.graphic.PolylineEntity({ positions: items, style: style }) if (graphic.distance < 100) continue this.layers.feature.addGraphic(graphic) } } }) } // async drawGeoServer(){ // var tileLayer = new mars3d.layer.GeoJsonLayer({ // url: 'http://11.100.6.5:8084/services/geoserver/gz-shp/ows?service=WFS&request=GetFeature&maxFeatures=20&outputFormat=application/json&typeName=gz-shp:YJFKWK2021&F-Auth-Key=YEF6D3NF1M', // // url: 'http://11.100.6.5:8084/services/geoserver/gz-shp/ows?service=WFS&request=GetFeature&maxFeatures=20&outputFormat=application/json&typeName=gz-shp:A_JJYZQ_XZJXZQ_PG_1000&F-Auth-Key=46EBBN247N', // }) // // this.map.addLayer(tileLayer) // } } } </script> <style rel="stylesheet/scss" lang="scss" scoped> /deep/ .mars3d-popup-close-button { top: 2em; right: 3em; } /deep/ .mars3d-popup{ position: absolute; /*top: 13.3em;*/ left: 12.6em; } /deep/ .mars3d-popup-content-wrapper { box-shadow: 0 0px 0px rgba(0,0,0,0); max-height: 1000px; } /deep/ .mars3d-popup-background { background-color: #00000000; background: url("../../assets/images/info-bg.png") no-repeat; background-size: 100% 100% } /deep/.mars3d-popup-close-button{ top: 10px; } .button { float: left; min-width: 300px; min-height: 100px; line-height: 100px; vertical-align: middle; position: relative; z-index: 10000; -webkit-backface-visibility: hidden; -moz-osx-font-smoothing: grayscale; } .button--round-s { border-radius: 5px; } .button--border-thin { border: 1px solid; } button--saqui { border-color: #ECEFF1; overflow: hidden; color: #fff; background: #37474f; -webkit-transition: background-color 0.3s ease-in, color 0.3s ease-in; transition: background-color 0.3s ease-in, color 0.3s ease-in; .button--inverted { background: #fff; color: #37474f; } button--inverted::after { color: #fff; } } .button--saqui::after { content: attr(data-text); position: absolute; top: 0; left: 0; width: 100%; height: 100%; padding: 1em 2em; color: #37474f; -webkit-transform-origin: -25% 50%; transform-origin: -25% 50%; -webkit-transform: rotate3d(0, 0, 1, 45deg); transform: rotate3d(0, 0, 1, 45deg); -webkit-transition: -webkit-transform 0.3s ease-in; transition: transform 0.3s ease-in; } .videoBox{ position:absolute; bottom:0; right:0; z-index:999; width:3.8rem; height:2.55rem; background:#000000; display:flex; align-items: start; flex-wrap: wrap; .videoBox-subBox{ width: 100%; height:100%; position:relative; } } .videoClose{ position: absolute; right: .05rem; top: .06rem; display: inline-block; color:#fff; font-size: .09rem; z-index:999; cursor: pointer; } </style>