之前写过一篇关于数据大屏及地图下钻的文章 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地图的人来说不太好下手,希望本文可以帮助到你.

如果有需要大家可以去以下地址下载源码学习,也欢迎star。

gitee源码地址:https://gitee.com/vijtor/vue-map-echarts

vue+echarts可视化大屏,全国地图下钻,页面自适应的更多相关文章

  1. Visual-platform,基于Vue的可视化大屏开发GUI框架

    visual-platform 基于Vue的可视化大屏开发GUI框架 ------ CreatedBy 漆黑小T 构建用于开发可视化大屏项目的自适应布局的GUI框架. github仓库: https: ...

  2. vue+echarts+datav大屏数据展示及实现中国地图省市县下钻

    随着前端技术的飞速发展,大数据时代的来临,我们在开发项目时越来越多的客户会要求我们做一个数据展示的大屏,可以直观的展示用户想要的数据,同时炫酷的界面也会深受客户的喜欢. 大屏展示其实就是一堆的图表能够 ...

  3. Qt编写数据可视化大屏界面电子看板系统

    一.前言 目前大屏大数据可视化UI这块非常火,趁热也用Qt来实现一个,Qt这个一站式超大型GUI超市,没有什么他做不了的,大屏电子看板当然也不在话下,有了QSS和QPainter这两个无敌的工具组合, ...

  4. Qt编写数据可视化大屏界面电子看板13-基础版

    一.前言 之前发布的Qt编写的可视化大屏电子看板系统,很多开发者比较感兴趣,也收到了很多反馈意见,纵观市面上的大屏系统,基本上都是B/S结构的web版本,需要在后台进行自定义配置模块,绑定数据源等,其 ...

  5. Qt编写数据可视化大屏界面电子看板12-数据库采集

    一.前言 数据采集是整个数据可视化大屏界面电子看板系统核心功能,没有数据源,这仅仅是个玩具UI,没啥用,当然默认做了定时器模拟数据,产生随机数据,这个可以直接配置文件修改来选择采用何种数据采集方法,总 ...

  6. Qt编写数据可视化大屏界面电子看板11-自定义控件

    一.前言 说到自定义控件,我是感觉特别熟悉的几个字,本人亲自原创的自定义控件超过110个,都是来自各个行业的具体应用真实需求,而不是凭空捏造的,当然有几个小控件也有点凑数的嫌疑,在编写整个数据可视化大 ...

  7. Qt编写数据可视化大屏界面电子看板9-曲线效果

    一.前言 为了编写数据可视化大屏界面电子看板系统,为了能够兼容Qt4和嵌入式linux系统,尤其是那种主频很低的,但是老板又需要在这种硬件上(比如树莓派.香橙派.全志H3.imx6)展示这么华丽的界面 ...

  8. Qt编写数据可视化大屏界面电子看板8-调整间距

    一.前言 在数据可视化大屏界面电子看板系统中,前期为了使用目标客户机,调整间距是必不可少的工作,QMainWindow中的QDockWidget,会默认生成布局和QSplitter调整宽高大小,鼠标移 ...

  9. Qt编写数据可视化大屏界面电子看板5-恢复布局

    一.前言 恢复布局这个功能在整个数据可视化大屏界面电子看板系统中非常有用,很多时候不小心把现有布局拖动乱了,(当然如果不想布局被拖动改动,可以修改配置文件中的MoveEnable参数来控制,默认为真表 ...

随机推荐

  1. StringUtils.isBlank(str)和StringUtils.isEmpty(str)的区别

    1.StringUtils.isEmpty(CharSequence cs)实现源码 public static boolean isEmpty(CharSequence cs) { return c ...

  2. UIImageView的序列帧动画

    #pragma mark - 开始动画 - (IBAction)startAnimation { // 1.1 加载所有的图片 NSMutableArray<UIImage *> *ima ...

  3. MATLAB基础学习篇(1)

    MATLAB中只定义了以2和10为底对数,其它 使用换底公式,例如:log8(7)=log7/log8. x=input('Please enter x:'); y=input('Please ent ...

  4. Springboot整合ElasticSearch进行简单的测试及用Kibana进行查看

    一.前言 搜索引擎还是在电商项目.百度.还有技术博客中广泛应用,使用最多的还是ElasticSearch,Solr在大数据量下检索性能不如ElasticSearch.今天和大家一起搭建一下,小编是看完 ...

  5. python数据分析入门笔记[1]

    1.Numpy: Numpy是python科学计算的基础包,它提供以下功能(不限于此): (1)快速高效的多维数组对象naarray (2)用于对数组执行元素级计算以及直接对数组执行数学运算的函数 ( ...

  6. ScaleFlux CSD 2000 在携程的应用实践

    一.业界背景与现状 近些年来,有三件事实在业界同时发生:     1.  业务的发展朝着"生产"和"使用"海量增长数据的方向演进.     2.  摩尔定律 的 ...

  7. 02编程语言与python介绍

    编程语言分类 机器语言:直接用计算机能理解的二进制指令去编写程序,是直接在控制计算机硬件 优点:运行效率高 缺点:开发效率低 1.开发一个简单的小功能都要哟个到非常多条数的二进制指令 2.二进制指令非 ...

  8. Netty高级应用及聊天室实战

    Netty 高级应用 1. 编解码器 概念:在网络应用中,需要实现某种编解码器.将原始字节数据与自定义消息数据进行相互转换.网络中都是以字节码的形式传输的. 对Netty而言,编解码器由两部分组成:编 ...

  9. PyTorch图文安装教程(Win10),含遇到的问题及解决办法

    PyTorch安装教程(Win10),含遇到的问题及解决办法 1. 环境准备 首先,打开PyTorch官网:https://pytorch.org/get-started/locally/ 向下可以看 ...

  10. Rainbond 5.6 版本发布,增加多种安装方式,优化拓扑图操作体验

    Rainbond 5.6 版本,主要致力于提升拓扑图操作效率以及快速安装体验,降低用户使用门槛. 主要功能点解读: 支持单机快速体验 为了方便在单机电脑上快速安装体验Rainbond,当前版本支持通过 ...