vue+echarts可视化大屏,全国地图下钻,页面自适应
之前写过一篇关于数据大屏及地图下钻的文章 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 = objData 100 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 false 121 } 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 false 136 } 137 }, 138 //绘制全国地图areaStatistic 139 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.value 213 } 214 }) 215 mapDataList = mapDataList.sort(function (a, b) { 216 return b.value - a.value 217 }); 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 : 0 229 this.option.visualMap.max = mapDataList.length > 0 ? mapDataList[0].value : 0 230 // 设置左上角当前位置 231 this.option.title[0].text = map === 'china' ? '全国' : map 232 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: 10 249 }, 250 ...mapOption.seriesOption, 251 data: data 252 }, 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 10 285 } 286 return 6 287 }, 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 // 动态显示tooltip 304 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.tooltipAutoplayIndex 313 }) 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.name 332 }) 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地图的人来说不太好下手,希望本文可以帮助到你.
如果有需要大家可以去以下地址下载源码学习。
gitee源码地址:https://gitee.com/vijtor/vue-map-echarts