之前写过一篇关于数据大屏及地图下钻的文章 https://www.cnblogs.com/weijiutao/p/13977011.html ,但是存在诸多问题,如地图边界线及行政区划老旧,无法自适应问题等,正好抽时间又整理了一下修改的思路.
之前的文章已经获取了一套新的全国地图的行政区划及边界线,接下来就可以根据这套区划来进行地图的编写了.先来看一下最后的呈现效果.
代码目录如下
地图采用了最新的行政区划及边界进行加载,具体获取方式在另一篇文章 https://www.cnblogs.com/weijiutao/p/15989290.html
地图边界下目录
这次代码与上一个版本的最大区别在于china.vue文件,如下
1 <template> 2 <div id="map-container"> 3 <el-button type="text" size="large" class="back" @click="back" v-if="deepTree.length > 1">返回</el-button> 4 <div class="echarts"> 5 <div id="map"></div> 6 </div> 7 </div> 8 </template> 9 10 <script> 11 12 import {getChinaJson, getProvinceJson, getCityJson, getDistrictJson} from "@/api/map"; 13 import {mapOption} from '@/config/mapOption' 14 import resize from '@/utils/resize' 15 16 17 export default { 18 mixins: [resize], 19 name: "china", 20 components: {}, 21 props: { 22 areaCode: { 23 type: String, 24 default: '000000000000' 25 }, 26 areaLevel: { 27 type: [String, Number], 28 default: 0 29 }, 30 areaName: { 31 type: String, 32 default: 'china' 33 }, 34 // 当前地图上的地区名字 35 mapNameList: { 36 type: Array, 37 default() { 38 return [] 39 } 40 }, 41 // 当前地图上的地区Code 42 mapCodeList: { 43 type: Array, 44 default() { 45 return [] 46 } 47 }, 48 // 地区统计数据 49 areaStatistic: { 50 type: Array, 51 default() { 52 return [] 53 } 54 } 55 }, 56 data() { 57 return { 58 chart: null, // 实例化echarts 59 mapDataList: [], // 当前地图上的地区 60 option: {...mapOption.basicOption}, // map的相关配置 61 deepTree: [],// 点击地图时push,点返回时pop 62 areaStatisticMapValue: {}, // 地图数据value, 只是amounts 63 areaStatisticMapData: {}, // 地图数据data,包含所有数据 64 areaLevelMap: { 65 'country': 0, 66 'china': 0, 67 'province': 1, 68 'city': 2, 69 'district': 3, 70 }, 71 tooltipAutoplay: null, // 提示框自动播放 72 tooltipAutoplayIndex: 0, // 提示框自动播放index 73 } 74 }, 75 beforeDestroy() { 76 if (!this.chart) { 77 return 78 } 79 this.chart.dispose() 80 this.chart = null 81 }, 82 mounted() { 83 this.$nextTick(() => { 84 this.initEcharts(); 85 this.chart.on('click', this.echartsMapClick); 86 this.chart.on('mouseover', this.echartsMapMouseover); 87 this.chart.on('mouseout', this.echartsMapMouseout); 88 }); 89 }, 90 watch: { 91 areaStatistic: { 92 handler(val) { 93 var objValue = {}, objData = {} 94 for (var i = 0; i < val.length; i++) { 95 objValue[val[i]['areaCode'].substr(0, 6)] = val[i].amounts * 1 96 objData[val[i]['areaCode'].substr(0, 6)] = val[i] 97 } 98 this.areaStatisticMapValue = objValue 99 this.areaStatisticMapData = objData100 this.initEcharts()101 },102 deep: true,103 }104 },105 methods: {106 // 初次加载绘制地图107 initEcharts() {108 //地图容器109 // this.$echarts.dispose(document.getElementById('map'))110 this.chart = this.$echarts.init(document.getElementById('map'));111 if (this.areaLevel === 0) {112 this.requestGetChinaJson();113 } else if (this.areaLevel === 1) {114 this.requestGetProvinceJSON({name: this.areaName, level: 'province', adcode: this.areaCode.substr(0, 6)})115 } else if (this.areaLevel === 2) {116 this.requestGetCityJSON({name: this.areaName, level: 'city', adcode: this.areaCode.substr(0, 6)})117 } else if (this.areaLevel === 3) {118 this.requestGetDistrictJSON({name: this.areaName, level: 'district', adcode: this.areaCode.substr(0, 6)})119 } else {120 return false121 }122 },123 // 地图点击124 echartsMapClick(params) {125 this.$emit('update:areaCode', params.data.adcode + '000000')126 this.$emit('update:areaName', params.data.name)127 this.$emit('update:areaLevel', this.areaLevelMap[params.data.level])128 if (params.data.level === 'province') {129 this.requestGetProvinceJSON(params.data);130 } else if (params.data.level === 'city') {131 this.requestGetCityJSON(params.data)132 } else if (params.data.level === 'district' && this.mapDataList.length > 1) {133 this.requestGetDistrictJSON(params.data)134 } else {135 return false136 }137 },138 //绘制全国地图areaStatistic139 requestGetChinaJson() {140 getChinaJson().then(res => {141 // console.log('china--->', res)142 this.$emit('update:areaLevel', 0)143 this.setJsonData(res)144 });145 },146 // 加载省级地图147 requestGetProvinceJSON(params) {148 getProvinceJson(params.adcode).then(res => {149 // console.log('province--->', res)150 this.$emit('update:areaLevel', 1)151 this.setJsonData(res, params)152 });153 },154 // 加载市级地图155 requestGetCityJSON(params) {156 getCityJson(params.adcode).then(res => {157 // console.log('city--->', res)158 this.$emit('update:areaLevel', 2)159 this.setJsonData(res, params)160 })161 },162 // 加载县级地图163 requestGetDistrictJSON(params) {164 getDistrictJson(params.adcode).then(res => {165 // console.log('district--->', res)166 this.$emit('update:areaLevel', 3)167 this.setJsonData(res, params)168 })169 },170 // 设置数据171 setJsonData(res, params) {172 var mapDataList = [];173 var mapNameList = [];174 var mapCodeList = [];175 for (var i = 0; i < res.features.length; i++) {176 var obj = {177 ...res.features[i].properties,178 value: this._mathRandom1000(),179 valueData: this._mathRandom1000(),180 };181 mapDataList.unshift(obj)182 mapNameList.unshift(res.features[i].properties.name)183 mapCodeList.unshift(res.features[i].properties.adcode + '000000')184 }185 this.mapDataList = mapDataList;186 this.$emit('update:mapNameList', mapNameList)187 this.$emit('update:mapCodeList', mapCodeList)188 this.setMapData(res, params)189 },190 // 设置地图信息191 setMapData(res, params) {192 if (this.areaName === 'china') {193 this.deepTree.push({194 mapDataList: this.mapDataList,195 params: {name: 'china', level: 'country', adcode: '100000'}196 });197 //注册地图198 this.$echarts.registerMap('china', res);199 //绘制地图200 this.renderMap('china', this.mapDataList);201 } else {202 this.deepTree.push({mapDataList: this.mapDataList, params: params});203 this.$echarts.registerMap(params.name, res);204 this.renderMap(params.name, this.mapDataList);205 }206 },207 // 渲染地图208 renderMap(map, data) {209 var mapDataList = data.map(item => {210 return {211 name: item.name,212 value: item.value213 }214 })215 mapDataList = mapDataList.sort(function (a, b) {216 return b.value - a.value217 });218 var pointData = []219 for (var i = 0; i < data.length; i++) {220 if (data[i].value != 0) {221 pointData.push({222 ...data[i],223 value: [data[i].center[0], data[i].center[1], data[i].value],224 })225 }226 }227 // 设置左下角数量范围值228 this.option.visualMap.min = mapDataList.length > 1 ? mapDataList[mapDataList.length - 2].value : 0229 this.option.visualMap.max = mapDataList.length > 0 ? mapDataList[0].value : 0230 // 设置左上角当前位置231 this.option.title[0].text = map === 'china' ? '全国' : map232 this.option.geo = {233 show: false,234 map: map,235 zoom: 1.2, //当前视角的缩放比例236 roam: true, //是否开启平游或缩放237 center: undefined,238 }239 this.option.series = [240 {241 name: map,242 mapType: map,243 zoom: 1, //当前视角的缩放比例244 roam: false, //是否开启平游或缩放245 center: undefined,246 scaleLimit: { //滚轮缩放的极限控制247 min: .5,248 max: 10249 },250 ...mapOption.seriesOption,251 data: data252 },253 {254 name: '散点',//series名称255 type: 'effectScatter',//散点类型256 coordinateSystem: 'geo',// series坐标系类型257 rippleEffect: {258 brushType: 'fill'259 },260 normal: {261 show: true,262 // 提示内容263 formatter: params => {264 return params.name;265 },266 position: 'top', // 提示方向267 color: '#fff'268 },269 emphasis: {270 show: true // 点271 },272 itemStyle: {273 normal: {274 color: '#F4E925',275 shadowBlur: 10,276 shadowColor: '#000'277 }278 },279 // symbol:'pin', // 散点样式'pin'(标注)、'arrow'(箭头)280 data: pointData,281 symbolSize: function (val) {282 // return val[2] / 100;283 if (val[2] === mapDataList[0].value) {284 return 10285 }286 return 6287 },288 showEffectOn: 'render', //加载完毕显示特效289 },290 ]291 //渲染地图292 this.chart.setOption(this.option, true)293 this.setTooltipAutoplay()294 },295 // 地图鼠标移入事件296 echartsMapMouseover() {297 clearInterval(this.tooltipAutoplay)298 },299 // 地图鼠标移出事件300 echartsMapMouseout() {301 this.setTooltipAutoplay()302 },303 // 动态显示tooltip304 setTooltipAutoplay() {305 clearInterval(this.tooltipAutoplay)306 // var index = 0; //播放所在下标307 // if(this.chart.dispatchAction) {308 this.tooltipAutoplay = setInterval(() => {309 this.chart.dispatchAction({310 type: 'showTip',311 seriesIndex: 0,312 dataIndex: this.tooltipAutoplayIndex313 })314 this.tooltipAutoplayIndex++315 if (this.tooltipAutoplayIndex >= this.mapDataList.length) {316 this.tooltipAutoplayIndex = 0;317 this.setTooltipAutoplay()318 }319 }, 6666)320 // }321 },322 // 返回323 back() {324 if (this.deepTree.length > 1) {325 this.deepTree.pop();326 this.mapDataList = this.deepTree[this.deepTree.length - 1].mapDataList;327 var areaName = this.deepTree[this.deepTree.length - 1].params.name;328 var areaCode = this.deepTree[this.deepTree.length - 1].params.adcode;329 var areaLevel = this.deepTree[this.deepTree.length - 1].params.level;330 var mapNameList = this.mapDataList.map(item => {331 return item.name332 })333 var mapCodeList = this.mapDataList.map(item => {334 return item.adcode + '000000'335 })336 this.$emit('update:areaCode', (areaCode === '100000' ? '000000' : areaCode) + '000000')337 this.$emit('update:areaName', areaName)338 this.$emit('update:areaLevel', this.areaLevelMap[areaLevel])339 this.$emit('update:mapNameList', mapNameList)340 this.$emit('update:mapCodeList', mapCodeList)341 this.renderMap(areaName, this.mapDataList);342 }343 }344 }345 }346 347 </script>348 349 <style lang="scss" scoped>350 #map-container {351 height: 66.6%;352 position: relative;353 354 .echarts {355 height: 100%;356 357 #map {358 width: 100%;359 height: 100%;360 }361 }362 363 .back {364 position: absolute;365 top: 55px;366 left: 5px;367 z-index: 9;368 //color: #24CFF4;369 font-weight: bolder;370 }371 }372 373 </style>
在上一套代码中,地图的边界上没有adcode(行政区划编码),这样就会导致在选取地区的时候只能根据汉字来进行匹配,导致不必要的错误,而最新抓去的行政区划里新增了adcode(行政区划)字段,这样就能根据该地区的行政区划来精准匹配.
同时在上一个版本代码里,也对直辖市和特别行政区做了特殊处理,因为他们没有三级县级地图,而这次版本由于引入adcode,可以直接匹配到指定行政区划中,减少和很多不必要的判断操作,如下图
做地图下钻本人也看过很多网上所说的,但是说的都不是很清楚,也没有专门对其进行代码的整理,这套代码是本人结合自身情况编写的,很多地方可能不是你想要的,需要对其进行取舍.
做地图其实最重要的就是地图边界线,自从echarts不再更新维护地图之后,对于初识echarts地图的人来说不太好下手,希望本文可以帮助到你.
如果有需要大家可以去以下地址下载源码学习,也欢迎star。
gitee源码地址:https://gitee.com/vijtor/vue-map-echarts