vue2地图下钻功能实现

一、背景

产品提了需求,想要一个功能,展示全国各省份信息,点击下钻展示市县。网上搜了下,自己整理一份,留作参考。

二、地图资源获取,大概两种方式。

一种是使用DataV api接口,但是仅限本地开始调试,线上环境慎用。

一种是下载资源包到本地环境。我是使用的第二种。

DataV数据可视化平台:https://datav.aliyun.com/portal/school/atlas/area_selector

三、项目引入

1 import chinaJson from '@/assets/china.json' // 引入全国省份地图包
2 import cityJson from '@/assets/city.json' // 引入全国市地图包

我这边是对数据做了预处理,删掉了南海诸岛的地图,只显示缩略图。

china.json文件

  第一步

第二步

 三、整体实现

  1 <template>
  2   <div class="bmap">
  3     <div class="back">
  4       <Button v-show="backVisible" type="primary" @click="goBack">返回</Button>
  5     </div>
  6     <div id="bmapBox" style="width: 100%; height: 100%"></div>
  7   </div>
  8 </template>
  9 
 10 <script>
 11 import * as echarts from 'echarts'
 12 import chinaJson from '@/assets/china.json' // 引入全国省份地图包
 13 import cityJson from '@/assets/city.json' // 引入全国市地图包
 14 
 15 export default {
 16   name: 'bmap',
 17   data() {
 18     return {
 19       myChart: null, // 地图实例
 20       zoom: 0.8, // 缩放比例,
 21       mapName: 'china', // 地图名称 Chian不显示南海诸岛
 22       mapGeoJson: chinaJson, // 地图json数据
 23       mapData: [
 24         { name: '天津市', value: 88 },
 25         { name: '上海市', value: 66 },
 26         { name: '重庆市', value: 42 },
 27         { name: '河北省', value: 99 },
 28         { name: '河南省', value: 52 },
 29         { name: '云南省', value: 33 },
 30         { name: '辽宁省', value: 22 },
 31         { name: '黑龙江省', value: 22 },
 32         { name: '湖南省', value: 22 },
 33         { name: '安徽省', value: 22 },
 34         { name: '山东省', value: 22 },
 35         { name: '新疆维吾尔自治区', value: 22 },
 36         { name: '江苏省', value: 22 },
 37         { name: '浙江省', value: 22 },
 38         { name: '江西省', value: 15 },
 39         { name: '湖北省', value: 33 },
 40         { name: '广西壮族自治区', value: 22 },
 41         { name: '甘肃省', value: 88 },
 42         { name: '山西省', value: 16 },
 43         { name: '内蒙古', value: 56 },
 44         { name: '陕西省', value: 33 },
 45         { name: '吉林省', value: 99 },
 46         { name: '福建省', value: 28 },
 47         { name: '贵州省', value: 25 },
 48         { name: '广东省', value: 33 },
 49         { name: '青海省', value: 88 },
 50         { name: '西藏自治区', value: 25 },
 51         { name: '内蒙古自治区', value: 1 },
 52         { name: '四川省', value: 45 },
 53         { name: '宁夏回族自治区', value: 36 },
 54         { name: '海南省', value: 22 },
 55         { name: '台湾省', value: 22 },
 56         { name: '香港特别行政区', value: 22 },
 57         { name: '澳门特别行政区', value: 22 }
 58       ], // 地图数据
 59       backVisible: false // 返回按钮是否显示
 60     }
 61   },
 62   methods: {
 63     // 点击返回,地图返回上一级
 64     goBack() {
 65       this.mapName = 'china'
 66       this.mapGeoJson = chinaJson
 67       this.mapData = [
 68         { name: '天津市', value: 88 },
 69         { name: '上海市', value: 66 },
 70         { name: '重庆市', value: 42 },
 71         { name: '河北省', value: 99 },
 72         { name: '河南省', value: 52 },
 73         { name: '云南省', value: 33 },
 74         { name: '辽宁省', value: 22 },
 75         { name: '黑龙江省', value: 22 },
 76         { name: '湖南省', value: 22 },
 77         { name: '安徽省', value: 22 },
 78         { name: '山东省', value: 22 },
 79         { name: '新疆维吾尔自治区', value: 22 },
 80         { name: '江苏省', value: 22 },
 81         { name: '浙江省', value: 22 },
 82         { name: '江西省', value: 15 },
 83         { name: '湖北省', value: 33 },
 84         { name: '广西壮族自治区', value: 22 },
 85         { name: '甘肃省', value: 88 },
 86         { name: '山西省', value: 16 },
 87         { name: '内蒙古', value: 56 },
 88         { name: '陕西省', value: 33 },
 89         { name: '吉林省', value: 99 },
 90         { name: '福建省', value: 28 },
 91         { name: '贵州省', value: 25 },
 92         { name: '广东省', value: 33 },
 93         { name: '青海省', value: 88 },
 94         { name: '西藏自治区', value: 25 },
 95         { name: '内蒙古自治区', value: 1 },
 96         { name: '四川省', value: 45 },
 97         { name: '宁夏回族自治区', value: 36 },
 98         { name: '海南省', value: 22 },
 99         { name: '台湾省', value: 22 },
100         { name: '香港特别行政区', value: 22 },
101         { name: '澳门特别行政区', value: 22 }
102       ]
103       this.init()
104       this.backVisible = false
105     },
106     // 渲染地图
107     renderChart() {
108       // 注册地图
109       echarts.registerMap(this.mapName, this.mapGeoJson)
110       // 根据 json 数据拼装 mapdata, 用于地图点击下钻时传递数据,主要有adcode、name
111       const mapdata = {}
112       this.mapGeoJson.features.map((item) => {
113         const { name, adcode, level } = item.properties
114         mapdata[name] = { name, adcode, level }
115       })
116       const _data = this.merData(mapdata, this.mapData) // 合并数据
117       // 配置option
118       this.setOption(this.mapName, _data)
119     },
120     merData(obj, arr) {
121       return arr.map((item) => {
122         const _data = obj[item.name] || {}
123         return Object.assign({}, _data, item) // 合并ite
124       })
125     },
126     // 设置地图option
127     setOption(name, data) {
128       const option = {
129         // tooltip 提示配置项
130         tooltip: {
131           formatter: function (params) {
132             // 根据需要进行数据处理或格式化操作
133             return `name: ${params.name}<br>value: ${params.value || 0}`
134           }
135         },
136         visualMap: {
137           show: false, // 不展示,只要数据映射功能
138           type: 'continuous',
139           showLabel: true,
140           calculabel: true,
141           left: '50',
142           min: 0,
143           max: 100,
144           inRange: {
145             color: ['#edfbfb', '#b7d6f3', '#40a9ed', '#3598c1', '#215096']
146           }
147         },
148         // 地理坐标系组件用于地图的绘制
149         geo: [
150           {
151             // 使用 registerMap 注册的地图名称。
152             map: name,
153             // 是否开启鼠标缩放和平移漫游。默认不开启。如果只想要开启缩放或者平移,可以设置成 'scale' 或者 'move'。设置成 true 为都开启
154             roam: true,
155             zoom: this.zoom,
156             // 图形上的文本标签,可用于说明图形的一些数据信息,比如值,名称等。
157             selectedMode: 'single',
158             label: {
159               show: true,
160               color: '#666666',
161               fontSize: 12,
162               formatter: (params) => {
163                 // 根据需要进行数据处理或格式化操作
164                 // 获取数值
165                 const _item = this.mapData.find((item) => item.name === params.name)
166                 let value = 0
167                 if (_item && _item.hasOwnProperty('value')) {
168                   value = _item.value
169                 }
170                 return `${value}\n${params.name}`
171               }
172             },
173             // 地图区域的多边形 图形样式。
174             itemStyle: {
175               // 地图区域的颜色
176               areaColor: '#71d5a1', // 绿色
177               // 图形的描边颜色
178               borderColor: '#2979ff' // 蓝色
179             },
180             // 设置高亮状态下的多边形和标签样式
181             emphasis: {
182               // 设置区域样式
183               itemStyle: {
184                 areaColor: '#ffff99', // 黄色
185                 borderColor: '#f29100' // 描边颜色黄色
186               },
187               // 设置字体
188               label: {
189                 fontSize: 16, // 16px
190                 color: '#f29100' // 白色
191               }
192             }
193           }
194         ],
195         series: [
196           {
197             type: 'map',
198             map: name,
199             geoIndex: 0,
200             roam: true,
201             zoom: this.zoom,
202             data
203           }
204         ]
205       }
206       this.myChart.setOption(option, true)
207     },
208     handleChartClick(params) {
209       console.log(params, 'click params')
210 
211       // 省份下钻
212       if (params.data) {
213         const { adcode, level } = params.data
214         if (level === 'province') {
215           if (adcode === 710000) {
216             this.$Message.warning('没有该省份数据!')
217             this.handleCancelHighlight({ target: null })
218             return
219           }
220           this.mapName = 'province'
221           const provinceJson = cityJson.features.filter((item) => {
222             if (item.properties && item.properties.parent) {
223               return item.properties.parent.adcode === adcode
224             }
225             return false
226           })
227           // 构建省份地图
228           const map = { type: 'FeatureCollection', features: provinceJson }
229           this.mapGeoJson = map
230           // mock市数据
231           const _mapdata = []
232           map.features.map((item) => {
233             const { name, adcode, level } = item.properties
234             _mapdata.push({ name, adcode, level, value: Math.floor(Math.random() * 100) })
235           })
236           this.mapData = _mapdata
237           this.renderChart()
238           this.backVisible = true
239         }
240       }
241     },
242     handleCancelHighlight(params) {
243       console.log(params, 'cancel highlight')
244 
245       if (!params.target) {
246         this.myChart.dispatchAction({
247           type: 'select'
248         })
249       }
250     },
251     init() {
252       this.myChart = this.myChart || echarts.init(document.getElementById('bmapBox'))
253       // 初始化中国地图
254       this.renderChart()
255       // 设置地图点击事件
256       this.myChart.on('click', this.handleChartClick)
257       // 点击地图外边
258       this.myChart.getZr().on('click', this.handleCancelHighlight)
259     },
260     resize() {
261       this.myChart.resize()
262     }
263   },
264   mounted() {
265     this.init()
266     window.addEventListener('resize', this.resize)
267   },
268   beforeDestroy() {
269     this.myChart.dispose()
270     window.removeEventListener('resize', this.resize)
271   }
272 }
273 </script>
274 
275 <style lang="less" scoped>
276 .bmap {
277   width: 100%;
278   height: 100%;
279   display: flex;
280   flex-direction: column;
281   .back {
282     flex-shrink: 0;
283     padding: 2px 0;
284   }
285   #bmapBox {
286     flex: 1;
287   }
288 }
289 </style>
View Code

 

posted @ 2025-04-25 14:33  剑气风尘  阅读(87)  评论(0)    收藏  举报