软件教程 2025年08月6日
0 收藏 0 点赞 207 浏览 6902 个字
摘要 :

文章目录 一、基础设置:防止403错误 二、数据与图表初始化 三、挂载阶段:初始化地图相关操作 四、初始化地图:获取数据并绘制 五、点击地图:切换地图层级 六、辅助方……




  • 一、基础设置:防止403错误
  • 二、数据与图表初始化
  • 三、挂载阶段:初始化地图相关操作
  • 四、初始化地图:获取数据并绘制
  • 五、点击地图:切换地图层级
  • 六、辅助方法:获取信息
    • (一)获取adcode和地图类型
    • (二)获取下级所有地名
  • 七、渲染地图:配置与更新

使用ECharts绘制中国地图是常见需求,今天就给大家分享一种利用CDN和阿里地图资源来实现的方法,而且无需下载JSON文件,方便又高效。

一、基础设置:防止403错误

在项目的index.html文件里,添加下面这行代码,它的作用是防止出现403错误:

<meta name=\"referrer\" content=\"no-referrer\" />

这行代码设置了页面的引用策略,避免在请求资源时因引用问题导致403错误,为后续顺利加载地图资源做好准备。

二、数据与图表初始化

接下来,要对数据赋值,同时初始化图表和配置项option。这里以初始化全国地图配置为例:

// 初始化绘制全国地图配置
option: {
  backgroundColor: \"transparent\", // 设置背景色透明
  // 必须设置
  tooltip: {
    show: false
  },
  // 地图阴影配置
}

在这段代码中,设置了地图的背景为透明,并且暂时隐藏了提示框tooltip。大家可以根据实际需求,对这些初始配置进行调整。

三、挂载阶段:初始化地图相关操作

mounted钩子函数中,主要进行地图初始化、获取地图以及获取图表的操作:

mounted() {
  this.initMap();
  this.getMap();
  this.myChart = window.echarts.init(document.getElementById(\"centerMap\"));
}

initMap()getMap()是自定义的方法,分别用于初始化地图数据和获取地图资源。window.echarts.init(document.getElementById(\"centerMap\"))则是使用ECharts的init方法,通过传入对应的DOM元素ID,来初始化一个ECharts图表实例。

四、初始化地图:获取数据并绘制

initMap函数主要负责从阿里地图获取数据,注册地图,绘制地图并绑定点击事件:

async initMap() {
  document.getElementById(\"back\").style.display = \"none\";
  await axios
  .get(`https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json`)
  .then((res) => {
      // 获取所有省份
      let shengAll = this.getChildMap(res.data);
      // 注册大地图
      window.echarts.registerMap(\"china\", res.data);
      // 绘制地图
      this.renderMap(\"china\", shengAll);
      // 绑定点击地图区域事件
      this.myChart.on(\"click\", this.clickMap);
    });
}

这里通过axios.get从阿里云的地图数据接口获取中国地图的JSON数据。拿到数据后,先调用getChildMap方法处理数据,获取所有省份信息。接着使用window.echarts.registerMap注册地图,renderMap方法绘制地图,最后绑定点击事件clickMap,方便后续实现点击地图的交互功能。

五、点击地图:切换地图层级

点击地图后,要根据点击的区域判断地图类型,并显示相应层级的地图:

clickMap(params) {
  document.getElementById(\"back\").style.display = \"block\";
  const name = params.name;
  const adcode = this.getAdcodeFromGeoJSON(name);
  const geoLevel = this.getAdcodeFromGeoLevel(name);
  if (geoLevel == \"province\" || geoLevel == \"city\") {
    if (name == \"台湾省\") {
      this.$message.warning(\"已经是最后一层地图了\");
    } else {
      axios
      .get(`https://geo.datav.aliyun.com/areas_v3/bound/${adcode}_full.json`)
      .then((res) => {
          // 注册省级地图
          window.echarts.registerMap(params.name, res.data);
          // 获取当前省下所有市
          let shiAll = this.getChildMap(res.data);
          this.renderMap(params.name, shiAll);
        });
    }
  } else {
    this.$message.warning(\"没有更小的地图了\");
    // this.renderMap(\"china\");
  }
}

这段代码中,先获取点击区域的名称name,再通过getAdcodeFromGeoJSONgetAdcodeFromGeoLevel方法获取对应的行政区划代码adcode和地图层级geoLevel。如果点击的是省份或城市,且不是台湾省,就获取该区域的详细地图数据,注册地图并绘制;如果点击的区域没有更小层级的地图,则给出提示。

六、辅助方法:获取信息

(一)获取adcode和地图类型

getAdcodeFromGeoJSON方法用于从GeoJSON数据中获取adcode

getAdcodeFromGeoJSON(name) {
  const geoJSON = window.echarts.getMap(this.option.geo.map).geoJSON;
  for (let feature of geoJSON.features) {
    if (feature.properties.name === name) {
      return feature.properties.adcode;
    }
  }
  return null;
}

这个方法通过遍历当前地图的GeoJSON数据,找到与点击名称匹配的区域,返回其adcode,找不到则返回null

getAdcodeFromGeoLevel方法用于获取地图类型:

getAdcodeFromGeoLevel(name) {
  const geoLevel = window.echarts.getMap(this.option.geo.map).geoJSON;
  for (let feature of geoLevel.features) {
    if (feature.properties.name === name) {
      return feature.properties.level;
    }
  }
  return null;
}

该方法与上面类似,只不过返回的是匹配区域的地图层级信息。

(二)获取下级所有地名

getChildMap方法用于获取下级所有地名:

getChildMap(data) {
  let childMapAll = [];
  // value为鼠标悬停地名显示的数据
  for (var i = 0; i < data.features.length; i++) {
    childMapAll.push({
      name: data.features[i].properties.name,
      value: 0
    });
  }
  return childMapAll;
}

这个方法遍历传入的地图数据,将每个区域的名称和初始值0组成对象,添加到数组中,最后返回包含所有下级地名的数组。

七、渲染地图:配置与更新

renderMap方法用于修改ECharts配置并重新渲染地图,实现地图的缩放、拖动等功能:

renderMap(map, data) {
  // 标题
  this.option.geo = {
    map: map,
    // 这里必须定义,不然后面series里面不生效
    tooltip: {
      show: false
    },
    label: {
      show: false
    },
    zoom: 1.03,
    silent: true, // 不响应鼠标时间
    show: true,
    roam: false, // 地图缩放和平移
    aspectScale: 0.75,
    layoutSize: \"108%\",
    itemStyle: {
      normal: {
        borderColor: \"rgba(147, 235, 248, 1)\",
        borderWidth: 0.5,
        color: {
          type: \"linear-gradient\",
          x: 0,
          y: 1500,
          x2: 2500,
          y2: 0,
          colorStops: [
            {
              offset: 0,
              color: \"#009DA1\" // 0% 处的颜色
            },
            {
              offset: 1,
              color: \"#005B9E\" // 50% 处的颜色
            }
          ],
          global: true // 缺省为 false
        },
        opacity: 0.5
      },
      emphasis: {
        areaColor: \"#2a333d\"
      }
    },
    // 地图区域的多边形 图形样式 阴影效果
    // z值小的图形会被z值大的图形覆盖
    top: \"18%\",
    left: \"center\",
    // 去除南海诸岛阴影 series map里面没有此属性
    regions: [
      {
        name: \"南海诸岛\",
        selected: false,
        emphasis: {
          disabled: true
        },
        itemStyle: {
          areaColor: \"#00000000\",
          borderColor: \"#00000000\"
        }
      }
    ],
    z: 1
  };
  this.option.series = [
    // 地图配置
    {
      type: \"map\",
      map: map,
      zoom: 1,
      tooltip: {
        show: false
      },
      label: {
        show: true, // 显示省份名称
        color: \"#04CFF5\",
        align: \"center\"
      },
      top: \"18%\",
      left: \"center\",
      aspectScale: 0.75,
      layoutSize: \"108%\",
      roam: false, // 地图缩放和平移
      itemStyle: {
        borderColor: \"#0FA3F0\", // 省分界线颜色  阴影效果的
        borderWidth: 1,
        areaColor: \"#065CAE\",
        opacity: 1
      },
      // 去除选中状态
      select: {
        disabled: true
      },
      emphasis: {
        // 聚焦后颜色
        disabled: false, // 开启高亮
        label: {
          align: \"center\",
          color: \"#04CFF5\"
        },
        itemStyle: {
          color: \"#ffffff\",
          areaColor: \"#0a8bd8\" // 阴影效果 鼠标移动上去的颜色
        }
      },
      z: 2
    },
    // 点
    {
      name: \"companyPoint\",
      type: \"effectScatter\",
      coordinateSystem: \"geo\",
      showEffectOn: \"render\",
      // zlevel: 2, // zlevel用于 Canvas 分层 相同的绘制在同一个canvas上
      rippleEffect: {
        number: 3, // 波纹数量
        period: 4, // 动画周期 数值越大,波动越慢
        scale: 3.5, // 动画中波纹的最大缩放比例
        brushType: \"stroke\" // 波纹的绘制方式 stroke fill
      },
      label: {
        show: false,
        position: \"right\",
        formatter: \"{b}\",
        color: \"#97e9e1\",
        fontSize: 14
      },
      symbol: \"circle\",
      symbolSize: 10,
      tooltip: {
        show: true,
        padding: 0,
        borderWidth: 0,
        backgroundColor: \"rgba(17, 132, 87,0.8)\",
        textStyle: {
          fontSize: 14,
          color: \"#fff\"
        },
        formatter: function (params) {
          // console.log(params, 222);
          var data = params.data;
          return (
            \"&nbsp;&nbsp;&nbsp;&nbsp;\" +
            \"所属用户:\" +
            data.name +
            \"<br>\" +
            \"&nbsp;&nbsp;&nbsp;&nbsp;\" +
            \"设备编号:\" +
            data.deviceId +
            \"<br>\" +
            \"&nbsp;&nbsp;&nbsp;&nbsp;\" +
            \"位置描述:\" +
            data.location +
            \"&nbsp;&nbsp;&nbsp;&nbsp;\" +
            \"<br>\" +
            \"&nbsp;&nbsp;&nbsp;&nbsp;\" +
            \"数据时间:\" +
            data.dataTime
          );
        }
      },
      z: 4
    }
  ];
  // 重新渲染echarts
  if (map == \"china\") {
    this.option.geo.layoutCenter = [\"50%\", \"65%\"];
    this.option.series[0].layoutCenter = [\"50%\", \"65%\"];
    this.option.geo.roam = false;
    this.option.series[0].roam = false; // 地图缩放和平移
  } else {
    this.option.geo.layoutCenter = [\"50%\", \"50%\"];
    this.option.series[0].layoutCenter = [\"50%\", \"50%\"];
    this.option.geo.roam = true;
    this.option.series[0].roam = true; // 地图缩放和平移
    this.myChart.on(\"georoam\", (params) => {
      var option = this.myChart.getOption(); //获得option对象
      if (params.zoom != null && params.zoom != undefined) {
        //捕捉到缩放时
        option.geo[0].zoom = option.series[0].zoom; //下层geo的缩放等级跟着上层的geo一起改变
        option.geo[0].center = option.series[0].center; //下层的geo的中心位置随着上层geo一起改变
        this.myChart.getZr().on(\"mousewheel\", (event) => {
          var zoom = option.geo[0].zoom;
          var zooms = option.series[0].zoom;
          var newZoom = event.wheelDelta > 0? zoom * 2 : zoom / 2;
          var newZooms = event.wheelDelta > 0? zooms * 2 : zooms / 2;
          newZoom = Math.max(1, Math.min(200, newZoom)); // 限制缩放级别
          newZooms = Math.max(1, Math.min(200, newZooms)); // 限制缩放级别
          this.myChart.setOption(
            {
              geo: {
                zoom: newZoom
              },
              series: [
                {
                  zoom: newZooms
                }
              ]
            },
            { lazyUpdate: true }// 是否延迟更新  
          );
        });
      } else {
        //捕捉到拖曳时
        option.geo[0].center = option.series[0].center; //下层的geo的中心位置随着上层geo一起改变
        this.myChart.setOption(option, { lazyUpdate: true }); //设置option// 是否延迟更新  
      }
    });
  }
  this.option.series[1].data = this.provinceData; // 假设数据加载到data变量中
  // // 更新图表数据
  this.myChart.setOption(this.option, true); // 第二个参数为true表示不合并之前的option,而是完全替换
  //随着屏幕大小调节图表
  window.addEventListener(\"resize\", () => {
    this.myChart.resize();
  });
}

这个方法配置了地图的各种属性,包括地图样式、缩放、拖动、标记点等。根据传入的地图名称,设置不同的布局和交互方式。最后更新图表数据,并添加监听窗口大小变化的事件,使图表能自适应屏幕变化。

通过以上步骤,我们就利用CDN和阿里地图资源,完成了ECharts中国地图的开发,并且实现了地图层级切换、缩放、拖动等功能。大家可以根据实际项目需求,对代码进行进一步优化和扩展。希望这篇文章能帮助到正在做相关开发的朋友们。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/6892.html

管理员

相关推荐
2025-08-06

文章目录 一、Promise基础回顾 二、Promise 与 axios 结合使用场景及方法 (一)直接返回 axios …

269
2025-08-06

文章目录 一、模块初始化时的内部机制 二、常见导出写法的差异分析 (一)写法一:module.exports…

107
2025-08-06

文章目录 一、ResizeObserver详解 (一)ResizeObserver是什么 (二)ResizeObserver的基本用法 …

683
2025-08-06

文章目录 一、前期准备工作 (一)下载相关文件 (二)安装必要工具 二、处理扣子空间生成的文件…

338
2025-08-06

文章目录 一、官方文档 二、自动解包的数据类型 ref对象:无需.value即可访问 reactive对象:保持…

371
2025-08-06

文章目录 一、Hooks的工作原理 二、在if语句中使用Hook会出什么岔子? 三、React官方的Hook使用规…

843
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号