展現西安市各區縣的地圖,點擊各區縣下鑽到各鄉鎮/街道,只能內網環境使用,不可用經過百度/高德地圖來實現。html
網絡上大部分地圖數據只是到省市,最多到區縣,再往下的數據就比較難找了;通過搜索,找到了一個能夠買地圖數據的地方,數據能夠精確到鄉鎮/街道,價格還比較划算;ios
地圖數據格式爲shp(shape格式),若是須要其餘的格式,得加點錢獲取好比svg、dbf、shx等額外格式的文件;
echarts支持的格式有geojson,此時咱們須要一個工具把shp格式的文件轉換爲geojson格式,推薦2種工具:json
這個工具是收費,每個月最多能夠轉換3次文件,上傳時網站會提示:axios
Don't forgot to upload all relevant files to your .SHP file - you need at least also .DXF and .SHX files uploaded together with your .SHP file!
不只要上傳shp格式,還要上傳dbf和shx等格式的文件,來得到更完整的地理數據,若是把全部格式的數據都上傳了,那麼生成的geojson可能會有問題(親測),因此只上傳3種格式是比較穩妥的辦法;瀏覽器
上傳後會跳轉到一個設置的界面,先不要點擊開始轉換按鈕,首先檢查一下轉換的編碼格式,默認爲UTF-8,若是是中文的地圖數據,最好把轉換格式切換爲GB18030-Chinese格式;而後點擊開始轉換就能夠了。緩存
轉換超過3個會提示下圖,這時能夠清一下瀏覽器緩存試試:網絡
轉換後能夠下載到.geojson格式的數據文件,放到項目中時,把.geojson格式手動修改成.json格式,就能夠被echarts使用了,直接import geojson格式的文件會報錯;app
同時上傳.dbf .shp .shx .prj格式的文件,而後點擊右上角的export,就會看到以下界面,選擇geoJSON,就完成了。echarts
關於具體如何導入json格式數據到echarts的方法,能夠參考官方示例。
如下是我本身的代碼:svg
<template> <div class="map-chart-wrapper" ref="myEchart" :style="{height:height,width:width, left: mapPosition.left, top: mapPosition.top}"> </div> <!-- '新城區': '①', '碑林區': '②', '蓮湖區': '③', --> </template> <script> import echarts from 'echarts'; import axios from 'axios'; import 'echarts/theme/macarons.js'; import xianshi from '../common/json/xiaan.json' import zhouzhixian from '../common/json/zhouzhi-cn.json' const cityMap = { '西安市': xianshi, '周至縣': zhouzhixian, } const cityStyleMap = { '西安市': { position: { left: '-112px', top: '0px', }, series: { left: 0, right: 0, top: '56px', bottom: '55px', } }, '周至縣': { position: { left: '-113px', top: '17px', }, series: { left: 0, right: 0, top: '30px', bottom: '0px', } }, } export default { props: { width: { type: String, default: '890px' }, height: { type: String, default: '517px' }, chartConfig:{ type: Object, default: ()=>({ title: null, backgroundColor: '#6a7985', seriesData: [], legendData: null, xAxisData: null, yAxisData: null, grid: {} }), }, mapData:{ type: Object, default: ()=>({}), }, }, data() { return { propsNew: '周至縣', chart: null, mapName: '', mapPosition: { left: '-117px', top: '36px' }, areaGeoMap: {}, districtList: [ { label: '周至縣', value: '周至縣', class: 'zhouzhixian', code: "610124000000"}, { label: '鄠邑區', value: '鄠邑區', class: 'huxian', code: "610118000000"}, { label: '長安區', value: '長安區', class: 'changan', code: "610116000000"}, { label: '雁塔區', value: '雁塔區', class: 'yanta', code: "610113000000"}, { label: '未央區', value: '未央區', class: 'weiyang', code: "610112000000"}, { label: '\u2460', value: '新城區', class: 'xincheng', code: "610102000000"}, { label: '\u2461', value: '碑林區', class: 'beilin', code: "610103000000"}, { label: '\u2462', value: '蓮湖區', class: 'lianhu', code: "610104000000"}, { label: '灞橋區', value: '灞橋區', class: 'baqiao', code: "610111000000"}, { label: '高陵區', value: '高陵區', class: 'gaoling', code: "610117000000"}, { label: '臨潼區', value: '臨潼區', class: 'lintong', code: "610115000000"}, { label: '閻良區', value: '閻良區', class: 'yanliang', code: "610114000000"}, { label: '藍田縣', value: '藍田縣', class: 'lantian', code: "610122000000"}, ], }; }, mounted() { this.createChart(); this.registerMap('西安市') }, beforeDestroy() { this.destroyChart(); }, watch: { chartConfig() { this.destroyChart(); this.initChart(); }, }, methods: { registerMap(name) { // 註冊地圖 axios.get(cityMap[name]).then((response) => { const geoJson = response.data console.log(geoJson) this.areaGeoMap = geoJson.features.reduce((acc, item) => { acc[item.properties.name] = item.properties.cp return acc }, {}) echarts.registerMap(name, geoJson); this.mapName = name; this.initChart() }).catch((error) => { alert('地圖數據未找到'+ error) }) }, createChart() { this.chart = echarts.init(this.$refs.myEchart, 'macarons'); window.addEventListener("resize", this.chart.resize); }, initChart() { // 清空當前實例,從而清空事件 this.chart.clear() // this.chart.off('click', this.areaClick) let titleSubtext = ''; let mapDown = true; if (this.mapName === '西安市') { mapDown = false titleSubtext = '\u2460' + ' 新城區\n' + '\u2461' +' 碑林區\n' + '\u2462'+ ' 蓮湖區\n'; } let styleData = cityStyleMap[this.mapName] this.mapPosition = styleData.position let seriesPos = styleData.series this.$emit('mapChange', { mapDown, name: this.mapName }) var levelColorMap = { '1': 'rgba(241, 109, 115, .8)', '2': 'rgba(255, 235, 59, .7)', '3': 'rgba(147, 235, 248, 1)' }; var COLORS = ["#070093", "#1c3fbf", "#1482e5", "#70b4eb", "#b4e0f3", "#ffffff"]; // 閃動點的數據 // const blinkDot = this.areaGeoMap[this.propsNew].concat(100) // console.log(blinkDot) // 把配置和數據放這裏 const transparentMap = 0 this.chart.setOption({ title: { text: '', subtext: titleSubtext, subtextStyle: { color: '#d7d7d7', fontSize: 14, lineHeight: 80, fontFamily: "Microsoft YaHei Light" }, left: '320px', top: '65px', }, tooltip: { trigger: 'item', formatter: (data) => { let key = data.name if (key === '\u2460') { key = '新城區' }else if (key === '\u2461') { key = '碑林區' }else if (key === '\u2462') { key = '蓮湖區' } return this.mapData[key] || key } }, series: [ { name: '', type: 'map', map: this.mapName, left: seriesPos.left, right: seriesPos.right, top: seriesPos.top, bottom: seriesPos.bottom, selectedMode : 'single', label: { normal: { fontSize: 14, color: '#d7d7d7', show: true, fontFamily: "Microsoft YaHei Light" }, emphasis: { show: true } }, itemStyle: { normal: { color: function(params){ return levelColorMap[params.value[3]]; }, // shadowOffsetX:5, // shadowOffsetY:5, // shadowBlur: 5, // shadowColor: 'rgba(255,255,255,0.5)', areaColor: 'rgba(255,255,255,0)', borderColor: new echarts.graphic.RadialGradient(0.3, 0.3, 0.8, [{ offset: 0, color: 'rgba(13,1,255,0)' }, { offset: 1, color: 'rgba(0,246,255,0)' }]) }, emphasis: { areaColor: 'rgba(0,246,255,0.2)', borderWidth: 0, label: { color: "#fff", } } }, data:[ ], nameMap: { // unicode 來源: http://xahlee.info/comp/unicode_circled_numbers.html '新城區': '\u2460', '碑林區': '\u2461', '蓮湖區': '\u2462', } }, { type: 'effectScatter', coordinateSystem: 'geo', // symbol: 'diamond', // showEffectOn: 'render', rippleEffect: { period: 15, scale: 6, brushType: 'fill' }, geoIndex: 0, hoverAnimation: true, itemStyle: { normal: { color: 'rgba(56,196,217,1)', shadowBlur: 10, shadowColor: '#fff' } }, data: [] } ] }); this.chart.on('click', this.areaClick) }, destroyChart() { if (this.chart) { window.removeEventListener("resize", this.chart.resize); this.chart.dispose(); this.chart = null; } }, refreshData(areacode = false) { const params = { handleBack: (data) => { } } if (areacode) { params.area_code = areacode; } this.$store.dispatch('summaryData', params); this.$store.dispatch('rateCredit', params); }, // 地圖的某塊區域點擊, @name參數爲地區名稱 areaClick(params) { console.log(params) const name = params.name const selected = params.data.selected if (selected) { if (name === '周至縣') { this.registerMap(name) } const areaObject = this.districtList.find((area) => { return area.value === name }) if (areaObject) { this.refreshData(areaObject.code) } } else { this.refreshData() } } } } </script> <style scoped> .map-chart-wrapper{ z-index: 9; position: absolute; } </style>
設計圖的地圖效果是3D的,爲了達到效果,將地圖的顏色設爲透明,使用設計圖做爲背景圖,此時須要調整echart地圖的比例(top/bottom/right/left),調整好以後,地圖選擇高亮和點擊事件,和地區名字仍是繼續用echart實現。最終結果:
參考文章