1. 程式人生 > >Leaflet+Echarts實現GIS地圖動態播放以及使用Echarts對點位資料詳情進行展示

Leaflet+Echarts實現GIS地圖動態播放以及使用Echarts對點位資料詳情進行展示

import 'leaflet/dist/leaflet.css' import L from 'leaflet' import Monitor from './../../../data/request/hbmis/monitor/data' import moment from 'moment' import Echarts from 'echarts' import Aqi from '../../../data/request/hbmis/aqi/aqi' import WebGis from '../../../data/request/hbmis/monitor/webgis'
import geoJson from '../overview/data/130000' import GeoCity from '../../../../static/js/city' import GeoCounty from '../../../../static/js/county' export default { props: { options: { type: Object, default() { return {} } }, point: { type: Object
, default() { return {} } }, isPoint: { type: Boolean, default: true }, isBasic: { type: Boolean, default: false }, mapType: { type: String
, default: 'city' }, type: { type: String, default: 'hour' } }, data() { return { map: null, layerGroup: null, layerGroupArr: [], layerControl: null, markerGroup: null, circle: null, center: [38.920469, 117.110617], geoJsonData: null, // 當前圖層 curBasic: null, curName: null, curCity: null, curCounty: null, curRound: null, curLayer: null, curPoint: null, curZoom: 7, // 查詢引數 params: { dataType: 2, starttime: '', endtime: '', ptids: '' }, currentData: {}, // 柱狀圖物件 myCharts: null, // 趨勢圖配置項 chartOptions: { tooltip: { trigger: 'axis' }, grid: { left: '1%', right: '4%', bottom: '1%', top: '4%', containLabel: true }, xAxis: [ { type: 'category', data: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'], splitLine: { show: false }, axisTick: { alignWithLabel: true } } ], yAxis: [ { type: 'value', splitLine: { show: false }, splitArea: { show: true, }, } ], series: [ { name: 'AQI', type: 'bar', itemStyle: { normal: { color: (d) => { return this.format_cur_color(d.data) } } }, data: [32.6, 25.9, 39.0, 26.4, 28.7, 70.7, 75.6, 82.2, 48.7, 58.8, 16.0, 32.3], } ] } } }, watch: { options() { this.loadData(this.options) this.load_point(this.point) if (this.isBasic) { if (this.mapType == 'city') { this.load_city() } if (this.mapType == 'county') { this.load_county() } } else { if (this.curCity instanceof Object) { this.curCity.remove() } if (this.curCounty instanceof Object) { this.curCounty.remove() } } }, point() { // this.load_point(this.point) }, isPoint() { if (this.isPoint) { this.load_point(this.point) } else { if (this.curPoint instanceof Object) { this.curPoint.remove() } } }, isBasic() { if (!this.isBasic) { this.load_basic() this.load_name() if (this.curCity instanceof Object) { this.curCity.remove() } if (this.curCounty instanceof Object) { this.curCounty.remove() } } else { if (this.curBasic instanceof Object) { this.curBasic.remove() } if (this.curName instanceof Object) { this.curName.remove() } if (this.mapType == 'city') { this.load_city() } if (this.mapType == 'county') { this.load_county() } } }, mapType() { if (this.curCity instanceof Object) { this.curCity.remove() } if (this.curCounty instanceof Object) { this.curCounty.remove() } if (this.mapType == 'city') { this.load_city() } if (this.mapType == 'county') { this.load_county() } }, type() { if (this.type == 'hour') { this.params.dataType = 2 } if (this.type == 'day') { this.params.dataType = 3 } if (this.type == 'month') { this.params.dataType = 5 } if (this.type == 'year') { this.params.dataType = 8 } } }, mounted() { this.init() }, methods: { // 載入底圖 load_basic() { if (!this.map || this.options == '') return if (this.curBasic && this.curBasic instanceof Object) { this.curBasic.remove() this.map.removeLayer(this.curBasic) this.curBasic = null } this.curBasic = L.tileLayer('http://t{s}.tianditu.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] }).addTo(this.map) }, // 載入城市名稱 load_name() { if (!this.map || this.options == '') return if (this.curName && this.curName instanceof Object) { this.curName.remove() this.map.removeLayer(this.curName) this.curName = null } this.curName = L.tileLayer('http://t{s}.tianditu.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'], zIndex: 201 }).addTo(this.map) }, // 載入城市GEOJSON資料 load_city() { if (!this.map || this.options == '') return if (this.curCity && this.curCity instanceof Object) { this.curCity.remove() this.map.removeLayer(this.curCity) this.curCity = null } this.curCity = L.geoJSON(GeoCity, { style(feature) { return { color: 'gray', fill: false, fillOpacity: 0, weight: 1 } } }).addTo(this.map); }, // 載入區縣GEOJSON資料 load_county() { if (!this.map || this.options == '') return if (this.curCounty && this.curCounty instanceof Object) { this.curCounty.remove() this.map.removeLayer(this.curCounty) this.curCounty = null } this.curCounty = L.geoJSON(GeoCounty, { style() { return { color: 'gray', fill: false, fillOpacity: 0, weight: 1 } }, }).addTo(this.map); }, // 載入省市邊界資料 load_round(data) { if (this.curRound && this.curRound instanceof Object) { this.curRound.remove() this.map.removeLayer(this.curRound) this.curRound = null } this.curRound = L.geoJSON(data, { style() { return { color: 'gray', fill: false, weight: 2, fillOpacity: 0 } }, }).addTo(this.map); }, // 載入插值資料 loadData(data) { if (!this.map || this.options == '') return if (this.curLayer && this.curLayer instanceof Object) { this.curLayer.remove() this.map.removeLayer(this.curLayer) this.curLayer = null } this.curLayer = L.geoJSON(data, { style(feature) { let lvalue = feature.properties.lvalue, color = '#EFEFEF' if (lvalue >= 0 && lvalue < 51) { color = 'rgba(0, 288, 0, 1)' } else if (lvalue >= 51 && lvalue < 101) { color = 'rgba(255, 255, 0, 1)' } else if (lvalue >= 101 && lvalue < 151) { color = 'rgba(255, 126, 0, 1)' } else if (lvalue >= 151 && lvalue < 201) { color = 'rgba(255, 0, 0, 1)' } else if (lvalue >= 201 && lvalue < 301) { color = 'rgba(153, 0, 76, 1)' } else if (lvalue >= 301 && lvalue <= 500) { color = 'rgba(126, 0, 35, 1)' } return { color: 'blue', fillColor: color, weight: 1, opacity: 0, fillOpacity: 0.8 } } }).addTo(this.map) }, // 載入站點 load_point(data) { let _this = this if (!this.map || this.options == '' || !this.isPoint) return if (this.curPoint && this.curPoint instanceof Object) { this.curPoint.remove() this.map.removeLayer(this.curPoint) this.curPoint = null } this.curPoint = L.geoJSON(data, { pointToLayer(geoJsonPoint, latlng) { let cvalue = geoJsonPoint.properties.value let curMark = _this.icon_create(cvalue, latlng, _this.curZoom) let mValue = geoJsonPoint.properties curMark.on('click', function () { // curMark.openPopup() _this.params.ptids = mValue.ptid _this.params.starttime = mValue.datatime _this.params.endtime = mValue.datatime _this.get_dataList(function () { let randomId = Math.floor(Math.random() * 1000) let phtml = _this.popup_create(_this.currentData, randomId, _this.params.dataType) console.log(randomId, 0) curMark.bindPopup(phtml).openPopup() _this.get_pointer_trend(randomId) }) }) return curMark } }).addTo(this.map) }, init() { let _this = this let normal1 = L.tileLayer('http://t{s}.tianditu.cn/DataServer?T=vec_w&X={x}&Y={y}&L={z}', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] }) let normal2 = L.tileLayer('http://t{s}.tianditu.cn/DataServer?T=cva_w&X={x}&Y={y}&L={z}', { subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'] }) let normal = [ // L.layerGroup([normal1]), // L.layerGroup([normal2]) ] this.map = L.map(_this.$el, { center: _this.center, zoom: 7, minZoom: 6, maxZoom: 12, layers: normal, }) // 事件繫結 this.map_event() this.load_basic() this.load_name() }, // 監聽地圖縮放 map_event() { this.map.on('zoom ', (val) => { console.log(val.target._zoom) this.curZoom = val.target._zoom this.load_point(this.point) }) this.map.on('move', () => { this.$emit('move') }) }, // icon生成器 icon_create(value, latlng, zoom) { let myMark = '' let myIcon = '' let iconStr = 'level-0' if (value >= 0 && value < 51) { iconStr = 'level-1' } else if (value >= 51 && value < 101) { iconStr = 'level-2' } else if (value >= 101 && value < 151) { iconStr = 'level-3' } else if (value >= 151 && value < 201) { iconStr = 'level-4' } else if (value >= 201 && value < 301) { iconStr = 'level-5' } else if (value >= 301 && value <= 500) { iconStr = 'level-6' } if (zoom > 8) { myIcon = L.divIcon({ html: `<div class="leaflet-icon-custom leaflet-icon-big leaflet-icon-${iconStr}">${value}</div>`, bgPos: [0, 0], className: 'leaflet-icon-custom-reset' }) myMark = L.marker(latlng, { icon: myIcon, iconSize: [24, 24] }) } else { myIcon = L.divIcon({ html: `<div class="leaflet-icon-custom leaflet-icon-small leaflet-icon-${iconStr}"></div>`, bgPos: [0, 0], className: 'leaflet-icon-custom-reset' }) myMark = L.marker(latlng, { icon: myIcon, iconSize: [8, 8] }) } return myMark }, // popup生成器 popup_create(value, id, type) { let popupStr = '' popupStr = ` <div class="leaflet-popup-custom"> <p class="leaflet-popup-title"> <span>站點詳情</span> </p> <div class="leaflet-popup-con"> <div class="leaflet-popup-abcon"> <div class="leaflet-row"> <div class="leaflet-col-1"> <p class="leaflet-popup-name">${value.ptname}</p> </div> <div class="leaflet-col-1"> <p class="leaflet-popup-txt" style="background:${this.format_cur_color(value.aqi)}">AQI</p> <p class="leaflet-popup-value">${value.aqi}</p> </div> </div> <div class="leaflet-row"> <div class="leaflet-col-1"> <p class="leaflet-popup-txt" style="background:${this.format_cur_color(value.iaqi_448A)}">PM2.5</p> <p class="leaflet-popup-value">${value.iaqi_448A}</p> </div> <div class="leaflet-col-1"> <p class="leaflet-popup-txt" style="background:${this.format_cur_color(value.iaqi_4486)}">PM10</p> <p class="leaflet-popup-value">${value.iaqi_4486}</p> </div> <div class="leaflet-col-1"> <p class="leaflet-popup-txt" style="background:${this.format_cur_color(value.iaqi_4402)}">SO2</p> <p class="leaflet-popup-value">${value.iaqi_4402}</p> </div> <div class="leaflet-col-1"> <p class="leaflet-popup-txt" style="background:${this.format_cur_color(value.iaqi_4467)}">NO2</p> <p class="leaflet-popup-value">${value.iaqi_4467}</p> </div> <div class="leaflet-col-1"> <p class="leaflet-popup-txt" style="background:${this.format_cur_color(value.iaqi_4404)}">CO</p> <p class="leaflet-popup-value">${value.iaqi_4404}</p> </div> <div class="leaflet-col-1"> <p class="leaflet-popup-txt" style="background:${this.format_cur_color(type == 2 ? value.iaqi_4471 : value.iaqi_4D71)}">O3</p> <p class="leaflet-popup-value">${type == 2 ? value.iaqi_4471 : value.iaqi_4D71}</p> </div> </div> <div class="leaflet-row"> <div class="leaflet-col-1"> <p class="leaflet-popup-txt">${type == 2 ? '近24小時趨勢圖' : '近一階段趨勢圖'}</p> <div class="leaflet-popup-chart" id="leaflet-popup-chart-${id}"></div> </div> </div> </div> </div> <p class="leaflet-popup-time"><small>更新於:${moment(value.datatime).format('YYYY/MM/DD HH:00')}</small></p> </div> ` return popupStr }, // 獲取當前站點小時資料 get_dataList(fn) { let _this = this; (async () => { try { let result = await Aqi.station_source_search(this.params) if (result.content && result.content[0]) { this.currentData = result.content[0] } console.log(this.currentData) fn && fn() } catch (error) { let msg = error.message || '資料獲取失敗' this.$message.error(msg) } })() }, // 格式化汙染等級樣式 format_cur_color(lvalue) { let color = '#EFEFEF' if (lvalue >= 0 && lvalue < 51) { color = 'rgba(0, 288, 0, 1)' } else if (lvalue >= 51 && lvalue < 101) { color = 'rgba(255, 255, 0, 1)' } else if (lvalue >= 101 && lvalue < 151) { color = 'rgba(255, 126, 0, 1)' } else if (lvalue >= 151 && lvalue < 201) { color = 'rgba(255, 0, 0, 1)' } else if (lvalue >= 201 && lvalue < 301) { color = 'rgba(153, 0, 76, 1)' } else if (lvalue >= 301 && lvalue <= 500) { color = 'rgba(126, 0, 35, 1)' } return color }, // 初始化圖表 init_bar_chart(id) { if (this.myCharts && this.myCharts.dispose) { this.myCharts.dispose() this.myCharts = null } let targetDom = document.getElementById(`leaflet-popup-chart-${id}`) this.myCharts = Echarts.init(targetDom) this.myCharts.setOption(this.chartOptions) }, // 獲取站點趨勢圖資料 async get_pointer_trend(id) { let _this = this let trendParams = {} let timeStr = '' if (_this.params.dataType == 2) { trendParams.starttime = moment(_this.params.starttime).subtract(24, 'h').format('YYYY-MM-DD HH:00:00') timeStr = 'HH:00' } else if (_this.params.dataType == 3) { trendParams.starttime = moment(_this.params.starttime).subtract(30, 'd').format('YYYY-MM-DD HH:00:00') timeStr = 'MM/DD' } else if (_this.params.dataType == 5) { trendParams.starttime = moment(_this.params.starttime).subtract(12, 'M').format('YYYY-MM-DD HH:00:00') timeStr = 'YYYY/MM' } else if (_this.params.dataType == 8) { trendParams.starttime = moment(_this.params.starttime).subtract(3, 'Y').format('YYYY-MM-DD HH:00:00') timeStr = 'YYYY' } trendParams.endtime = _this.params.endtime trendParams.dataType = _this.params.dataType trendParams.ptids = _this.params.ptids try { let result = await WebGis.get_gisdata_trend(trendParams) _this.chartOptions.series[0].data = result.data.series[0].data _this.chartOptions.xAxis[0].data = result.data.xAxis.map((m) => { return moment(m).format(timeStr) }) _this.init_bar_chart(id) } catch (error) { let msg = error.message || '資料獲取失敗' this.$message.error(msg) } }, } }