当前位置:首页 » 《休闲阅读》 » 正文

如何在 Vue3 中结合 ECharts 实现交互式的中国地图钻取功能

21 人参与  2024年09月09日 16:41  分类 : 《休闲阅读》  评论

点击全文阅读


在许多业务场景中,我们需要展示与地理位置相关的数据。本文将详细介绍如何在 Vue3 中结合 ECharts 库来实现一个可交互的中国地图,并支持用户通过点击地图上的省份来查看更详细的地区数据。

实现效果

29fe8a114050403d8748ac7ac513681d.png807a9f33b6fc433d92411cb4193681d6.png

最终的效果是:用户可以点击中国地图上的任意省份,然后页面会展示该省份的详细信息;同时提供一个“返回”按钮,用户可以点击它回到初始的中国地图视图。

技术栈

Vue.js 3:用于构建前端应用程序。ECharts:用于数据可视化。Fetch:用于请求本地JSON文件。

步骤详解

1. 模板定义

在 Vue3 组件的模板中定义一个用于显示地图的容器和一个返回按钮。

<template>  <div style="position: relative; width: 100%; height: 100%">    <div id="map" ref="mapRef" style="width: 100%; height: 400px" />    <span v-if="isBack" class="go-back" @click="gotoParent">返回</span>  </div></template>

2. 请求省份 JSON 数据

使用Fetch加载中国省份的地图数据(GeoJSON 格式)。

async function fetchMapJson(adcode) {  // 使用 fetch 加载 JSON 文件  const response = await fetch("/json/map/" + adcode + ".json");  mapJsonData.value = await response.json();}

3. 注册地图数据

使用 ECharts 的 registerMap 方法来注册地图数据。

// 注册地图数据function handleRegisterMap(regionName) {  mapChart.value = echarts.init(mapRef.value); // 初始化地图  echarts.registerMap(regionName, mapJsonData.value);  const option = {    geo: {      map: regionName,      roam: true,      label: {        normal: { show: false },        emphasis: { show: true },      },      itemStyle: {        normal: {          areaColor: "#2B91B7",          borderColor: "#111",        },        emphasis: {          areaColor: "#0489d6",        },      },    },    series: [      {        type: "scatter",        coordinateSystem: "geo",        map: regionName,        data: [], // 这里可以填充省份数据        label: {          normal: {            show: false,          },          emphasis: {            show: true,            textStyle: {              color: "#fff",            },          },        },        itemStyle: {          normal: {            areaColor: "#2B91B7",            borderColor: "#aaa",          },          emphasis: {            areaColor: "#0489d6",          },        },      },    ],  };  mapChart.value.setOption(option);}

4. 添加省份点击事件

// 添加省份点击事件let returnArray = ref([]);const handleClickMap = async (params) => {  if (params.componentType === "geo" && params.name !== "") {    // 查找地理编码    let adcode = null;    const features = mapJsonData.value.features;    const filterArray = features.filter((item) => {      return item.properties.name === params.name;    });    if (filterArray && filterArray.length > 0) {      adcode = filterArray[0].id;    }    const regionName = params.name;    if (adcode) {      isBack.value = true;      await fetchMapJson(adcode);      returnArray.value.push({        adcode: adcode,        regionName: regionName,        mapJsonData: JSON.stringify(mapJsonData.value),      });      // 清除当前地图选项      mapChart.value.clear();      // 刷新地图实例      mapChart.value.resize();      handleRegisterMap(regionName);    }  } else if (params.componentType === "series") {    // 点击的数据    const data = params.data;    console.log("data", data);  }};

5. 初始化中国地图

设置 ECharts 实例,并配置地图的基本选项。

let chinaJsonData = ref({}); // 中国地图数据onMounted(async () => {  // 使用 fetch 加载 JSON 文件  await fetchMapJson(100000);  chinaJsonData.value = mapJsonData.value; // 先保留中国地图json  handleRegisterMap("china");  isBack.value = false;  returnArray.value.push({    adcode: 100000,    regionName: "china",    mapJsonData: JSON.stringify(chinaJsonData.value),  });  mapChart.value.on("click", handleClickMap);  window.addEventListener("resize", () => {    mapChart.value.resize();  });});

6. 返回上级

实现返回按钮的功能,当点击返回时可以返回它的上一级,直至中国地图。

// 返回上级async function gotoParent() {  if (isBack.value) {    if (returnArray.value.length > 0) {      returnArray.value.pop();      let backMap = returnArray.value.slice(-1);      if (backMap && backMap.length > 0) {        mapJsonData.value = JSON.parse(backMap[0].mapJsonData);        // 清除当前地图选项        mapChart.value.clear();        // 刷新地图实例        mapChart.value.resize();        handleRegisterMap(backMap[0].regionName);        if (backMap[0].adcode == 100000) {          isBack.value = false;          returnArray.value = [            {              adcode: 100000,              regionName: "china",              mapJsonData: JSON.stringify(chinaJsonData.value),            },          ];        }      }    } else {      isBack.value = false;    }  }}

完整代码

为了便于理解,以下是完整的组件代码示例:

<template>  <div style="position: relative; width: 100%; height: 100%">    <div id="map" ref="mapRef" style="width: 100%; height: 400px" />    <span v-if="isBack" class="go-back" @click="gotoParent">返回</span>  </div></template><script setup>import * as echarts from "echarts";import { ref, onMounted, onBeforeUnmount } from "vue";const mapRef = ref(null);let mapJsonData = ref({});let mapChart = ref(null);let isBack = ref(false); // 加标记,是否返回上一级// 根据地理编号请求json数据async function fetchMapJson(adcode) {  // 使用 fetch 加载 JSON 文件  const response = await fetch("/json/map/" + adcode + ".json");  mapJsonData.value = await response.json();}// 注册地图数据function handleRegisterMap(regionName) {  mapChart.value = echarts.init(mapRef.value); // 初始化地图  echarts.registerMap(regionName, mapJsonData.value);  const option = {    geo: {      map: regionName,      roam: true,      label: {        normal: { show: false },        emphasis: { show: true },      },      itemStyle: {        normal: {          areaColor: "#2B91B7",          borderColor: "#111",        },        emphasis: {          areaColor: "#0489d6",        },      },    },    series: [      {        type: "scatter",        coordinateSystem: "geo",        map: regionName,        data: [], // 这里可以填充省份数据        label: {          normal: {            show: false,          },          emphasis: {            show: true,            textStyle: {              color: "#fff",            },          },        },        itemStyle: {          normal: {            areaColor: "#2B91B7",            borderColor: "#aaa",          },          emphasis: {            areaColor: "#0489d6",          },        },      },    ],  };  mapChart.value.setOption(option);}// 添加省份点击事件let returnArray = ref([]);const handleClickMap = async (params) => {  if (params.componentType === "geo" && params.name !== "") {    // 查找地理编码    let adcode = null;    const features = mapJsonData.value.features;    const filterArray = features.filter((item) => {      return item.properties.name === params.name;    });    if (filterArray && filterArray.length > 0) {      adcode = filterArray[0].id;    }    const regionName = params.name;    if (adcode) {      isBack.value = true;      await fetchMapJson(adcode);      returnArray.value.push({        adcode: adcode,        regionName: regionName,        mapJsonData: JSON.stringify(mapJsonData.value),      });      // 清除当前地图选项      mapChart.value.clear();      // 刷新地图实例      mapChart.value.resize();      handleRegisterMap(regionName);    }  } else if (params.componentType === "series") {    // 点击的数据    const data = params.data;    console.log("data", data);  }};// 返回上级async function gotoParent() {  if (isBack.value) {    if (returnArray.value.length > 0) {      returnArray.value.pop();      let backMap = returnArray.value.slice(-1);      if (backMap && backMap.length > 0) {        mapJsonData.value = JSON.parse(backMap[0].mapJsonData);        // 清除当前地图选项        mapChart.value.clear();        // 刷新地图实例        mapChart.value.resize();        handleRegisterMap(backMap[0].regionName);        if (backMap[0].adcode == 100000) {          isBack.value = false;          returnArray.value = [            {              adcode: 100000,              regionName: "china",              mapJsonData: JSON.stringify(chinaJsonData.value),            },          ];        }      }    } else {      isBack.value = false;    }  }}let chinaJsonData = ref({}); // 中国地图数据onMounted(async () => {  // 使用 fetch 加载 JSON 文件  await fetchMapJson(100000);  chinaJsonData.value = mapJsonData.value; // 先保留中国地图json  handleRegisterMap("china");  isBack.value = false;  returnArray.value.push({    adcode: 100000,    regionName: "china",    mapJsonData: JSON.stringify(chinaJsonData.value),  });  mapChart.value.on("click", handleClickMap);  window.addEventListener("resize", () => {    mapChart.value.resize();  });});onBeforeUnmount(() => {  // 移除地图点击事件监听器  mapChart.value.off("click", handleClickMap);});</script><style scoped>#map {  width: 100%;  height: 400px;}.go-back {  display: inline-block;  position: absolute;  right: 20px;  top: 20px;  z-index: 9999;  cursor: pointer;  color: #36cfff;}</style>

总结

通过上述步骤,您可以在 Vue3 应用中实现一个交互式的中国地图,支持省份点击和返回功能。


点击全文阅读


本文链接:http://zhangshiyu.com/post/157448.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1