vue+echarts可视化大屏,全国地图下钻,页面自适应
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地图的人来说不太好下手,希望本文可以帮助到你.
如果有需要大家可以去以下地址下载源码学习,也欢迎star。
gitee源码地址:https://gitee.com/vijtor/vue-map-echarts
以上是 vue+echarts可视化大屏,全国地图下钻,页面自适应 的全部内容, 来源链接: utcz.com/z/380976.html