echarts+vue实现中国地图板块渲染+省市区跳转渲染

  1. 首先绘画地图板块的坐标数据,阿里云免费的省市区坐标数据,链接https://datav.aliyun.com/portal/school/atlas/area_selector, 看自己嵌套情况下载数据粒度,如果需要省市区跳转就全部下载, 文件下载后市和区的文件名是重名的 需要自己区分 还有一些地区的adcode嵌套的更深需要自己判断查找文件
  2. 加载坐标文件,通过echarts渲染地图板块
js 复制代码
// 地图模版
<div class="initEchartsMap" id="mapContainer"></div>

import * as echarts from 'echarts'
import chinaGeoJson from '@/assets/map/china.json' // 导入中国地图 GeoJSON 数据


export default {
    data(){
        return {
            // 地图数据
            mapDatas: {},
            //当前点击的层级
            currentIndex: 1,
        }
    },
    
    mounted(){
        //这里根据t返回的地区名称加载坐标数据  默认加载全国
        const response = await import(`@/assets/map/${t}.json`)
        console.log(response, '=>respinse')
        this.mapData = response.default
        //初始化地图数据
        this.initMap(response.default)
           
           
    },
    methods:{
        initMap(mapJson) {
            this.mapInstance = echarts.init(document.getElementById('mapContainer'))
            echarts.registerMap(this.regionCity, mapJson) // 注册地图
            this.loadMap(this.regionCity)
      },
         
      //绘画地图
      loadMap(regionName) {
        let that = this
        const options = {
          tooltip: {
            trigger: 'item',
            position: function(point, params, dom, rect, size) {
              return [point[0] - 40, point[1] - 60] // 手动调整位置(x, y)//控制地图板块位置
            },

            formatter: params => {
              const data = this.tooltipData.find(
                item => item.rangeName === params.name,
              )
              if (data) {
                return this.tooltipTemplate(data)  //自定义鼠标划过显示的模版
              }
              return params.name
            },

            backgroundColor: '#fff',
            padding: [0, 0],
            borderRadius: 5,
            boxShadow: '0 2px 5px rgba(0, 0, 0, 0.2)',
            borderWidth: 0, // 禁用边框
          },
          grid: {
            right: '0%',
            top: '0%',
            bottom: '5%',
            width: '100%',
            height: '100%',
          },

          select: {
            label: {
              show: false,
            },
            itemStyle: {
              color: '#fff',
              areaColor: '#D7EEFF',
            },
          },

          series: [
            {
              name: '区域',
              type: 'map',
              map: regionName, //当前加载的区域名称
              roam: false, // 开启缩放和拖拽
              itemStyle: {
                normal: {
                  areaColor: '#DEF0FF',
                  borderColor: '#ACD8FF',
                  borderWidth: 1.3
                  shadowBlur: 15,
                  shadowColor: 'rgba(60,107,255,0.8)',
                  shadowOffsetX: 7,
                  shadowOffsetY: 6,
                },
                emphasis: {
                  areaColor: '#87D1FC',
                  borderWidth: 1.6,
                  shadowBlur: 25,
                },

              },

              label: {
                show: false, // 禁用区域名称显示
                fontSize: 0,
              },
               //获取后面点击所获取的地区名称和adcode
              data: this.mapData.features.map(item => ({
                name: item.properties.name,
                value: item.properties.adcode,
                item: item,
              })), // 数据可以动态绑定
              // 动态设置地图的中心点和缩放级别
              geo: {
                center: [0, 0], // 设置地图的中心点
              },

            },

          ],

        }

        this.mapInstance.setOption(options)
        
        //echarts自适应记
        window.addEventListener('resize', () => {
          this.mapInstance.resize()
        })

        // 添加点击事件监听

       
        that.mapInstance.off('click') // 避免重复绑定
        
        that.mapInstance.on('click', params => {
        
          this.regionProvince = params.name
          //这里因为数据问题需要手动查找,我就直接禁用了
          const restrictedRegions = ['台湾省', '南海诸岛', '海南省', '上海市'] // 禁止点击的特殊区
 
          const currentRegion = params.name // 当前点击区域的名称
          console.log(currentRegion, '当前点击的区域')

          let valisCode = params.data.item.properties.parent.adcode
          // 判断是否是禁止点击的区域
          if (restrictedRegions.includes(currentRegion)) {
            console.log(`${currentRegion} 不允许点击`)
            // this.$message.warning(`${currentRegion} 暂无数据`)
            return // 阻止点击操作
          }

          // 判断当前是否为第三级,使用自定义逻辑
          // 假设 yourCondition 是判断第三级的方法(如通过 params 层级属性判断)
          const isThirdLevel = this.currentIndex == 3 // 假设第三级的数据含有 level 属性
          if (isThirdLevel) {
            console.log('当前为第三级,禁止点击')

            // this.$message.warning(`${currentRegion} 暂无数据`)

            return // 阻止点击操作
          }
          //切换地图数据的操作
          this.handleMapClick(params)

        })

      },
      async handleMapClick(params) {
        const { name, value } = params // 当前点击的区域名称
        if (!name) return
        this.loading = true
        try {
          const geoJson = await this.fetchGeoJson(
            name,
            value,
            params.data.item.properties.parent.adcode,
          ) // 获取下一级地图数据
          if (geoJson) {
            this.initMap(mapJson)
          }

        } catch (error) {
          console.error('无法加载该区域数据:', error)
        }

      },
     

      async fetchGeoJson(regionName, value, parAdcode) {

        let t = 'china'

        let that = this
            //这里判断一下点击是否是市
        if (

          regionName.includes('市') &&

          (value === 110000 ||

            value === 120000 ||

            value === 310000 ||

            value === 500000)

        ) {

          this.currentIndex = 2

          this.regionCity = regionName

          t = regionName + 'd'   //这里加d时因为我的文件名称
            
          //这里要自己处理一下获取的数据,直接获取的echarts识别不了
          let nationalMapRangeList = {

            type: 'FeatureCollection',

            features: [],

          }
           //这里应该做一个封装的
          const response = await import(`@/assets/map/${t}.json`)
        
          response.default.features.map(item => {
            if (item.properties.parent.adcode === value) {
              nationalMapRangeList.features.push(item)
            }
          })
          this.mapData = nationalMapRangeList
          return nationalMapRangeList

        }

        if (this.currentIndex === 1) {

          t = regionName + 'c'

          this.currentIndex = 2
          this.regionCity = regionName

          try {

            const response = await import(`@/assets/map/${t}.json`)

            console.log(response, 'respinse1')

            this.mapData = response.default

            return response.default

          } catch (error) {

            console.error('加载 GeoJSON 数据失败:', error)

            return null

          }

        } else if (this.currentIndex === 2) {

          this.currentIndex = 3

          t = this.regionCity + 'd'

          let nationalMapRangeList = {

            type: 'FeatureCollection',

            features: [],

          }

          const response = await import(`@/assets/map/${t}.json`)

          response.default.features.map(item => {

            if (item.properties.parent.adcode === value) {

              nationalMapRangeList.features.push(item)

            }

          })

          this.mapData = nationalMapRangeList
          return nationalMapRangeList
        }

      },

    },
    }

}

这样就实现了一个 基础的 地图板块渲染+省市区跳转

相关推荐
影子信息27 分钟前
vue 前端动态导入文件 import.meta.glob
前端·javascript·vue.js
青阳流月28 分钟前
1.vue权衡的艺术
前端·vue.js·开源
RunsenLIu29 分钟前
基于Vue.js + Node.js + MySQL实现的图书销售管理系统
vue.js·mysql·node.js
样子201832 分钟前
Vue3 之dialog弹框简单制作
前端·javascript·vue.js·前端框架·ecmascript
kevin_水滴石穿33 分钟前
Vue 中报错 TypeError: crypto$2.getRandomValues is not a function
前端·javascript·vue.js
翻滚吧键盘33 分钟前
vue文本插值
javascript·vue.js·ecmascript
华子w90892585934 分钟前
基于 SpringBoot+Vue.js+ElementUI 的 “花开富贵“ 花园管理系统设计与实现7000字论文
vue.js·spring boot·elementui
老家的回忆3 小时前
jsPDF和html2canvas生成pdf,组件用的elementplus,亲测30多页,20s实现
前端·vue.js·pdf·html2canvas·jspdf
hackchen4 小时前
从0到1解锁Element-Plus组件二次封装El-Dialog动态调用
前端·vue.js·elementui
用户7579419949704 小时前
Vue响应式原理推导过程
vue.js·响应式设计