【vue】Echarts3D地图下钻

需求分析

1.gif
地图下钻是一个非常常见的功能需求,本篇文章会细致讲解如何在Vue3中使用Eharts-gl渲染出3D地图,并且实现地图下钻和返回上级地图的完整功能。
github项目demo地址:点击这里

注意此项目为vue3版本,vue2版本在仓库分支里
给个星星吧!!不定期更新此demo,一般只更新vue3的版本,2版本自行迁移即可。

demo依赖版本确认:

"axios": "^1.3.5",
"echarts": "^5.2.2",
"echarts-gl": "^2.0.9",
"vue": "^3.2.47"

我把需求拆分成两个主要功能模块:初始化地图更新地图功能构思:

  1. 初始化地图
  • 初始化DOM节点
  • initmap初始化地图 -> getMapJSON 获取地图JSON并且初始化地图配置项data数据 -> getOption获得地图总配置项 -> updateMap更新配置项
  • 监听点击事件(地图下钻)
  1. 更新地图
  • updateMap
  • 点击区域下钻省市区地图
  • backMap返回上级地图

需求实现

功能介绍

点击区域:初始化地图 => 给地图添加点击事件 => 拿到用户点击的区域名称 => 保存用户点击的区域做历史记录 => 请求接口获取到该区域的JSON数据 => 重新渲染
点击返回图标: 遍历历史记录 => 弹出当前历史记录的地图信息 => 找到要返回上一级的地图信息 => 重新渲染地图

程序运行流程图

关于使用用户内存保存历史记录,还是请求接口保存的问题:
接口性能还是比较高的,存在内存数据及时性就不太准确

image.pngimage.png

总体功能

1.地图下钻和返回上级功能

总体代码

vue3 版本

<template>
  <div class="investment-screen">
    <svg
      style="position: absolute; left: 20px; top: 20px; cursor: pointer"
      @click="backMap"
      t="1681180771137"
      class="icon"
      viewBox="0 0 1024 1024"
      version="1.1"
      xmlns="http://www.w3.org/2000/svg"
      p-id="3427"
      width="200"
      height="200"
    >
      <path
        d="M426.666667 384V213.333333l-298.666667 298.666667 298.666667 298.666667v-174.933334c213.333333 0 362.666667 68.266667 469.333333 217.6-42.666667-213.333333-170.666667-426.666667-469.333333-469.333333z"
        p-id="3428"
        fill="#ffffff"
      ></path>
    </svg>
    <div class="map-chart" id="mapEchart"></div>
  </div>
</template>

<script lang="ts" setup>
import * as echarts from "echarts";
import "echarts-gl"; //3D地图插件
import { onMounted, ref } from "vue";
import axios from "axios";

/**
 * 初始化地图
 */

// 定义echarts方法
const chartMap = async () => {
  // 初始化dom
  const myChart = echarts.init(
    <HTMLElement>document.getElementById("mapEchart")
  );
  // 初始化map
  initMap(myChart, "map", "100000");
  // 添加点击事件
  myChart.on("click", (e: any) => {
    console.log(e);
    const newName: string = e.name;
    if (e.value.level === "district") return alert("该地区已经无法下钻");
    // 添加历史记录
    historyMapData.value.push(e.value);
    // 初始化地图
    initMap(myChart, newName, e.value.adcode);
  });
  //让可视化地图跟随浏览器大小缩放
  window.addEventListener("resize", () => {
    myChart.resize();
  });
};
// 初始化图表
const initMap = async (
  chartDOM: echarts.ECharts,
  geoName: string,
  adcode: string
) => {
  // 清除echarts实例
  chartDOM.clear();
  // 请求map的json
  const mapData = await getMapJSON(adcode, geoName);
  // 图表配置项
  const option = getOption(geoName, mapData);
  // 渲染配置
  chartDOM.setOption(option);
};

/**
 * 地图配置项
 */

// 请求地图json数据,并过滤成地图data配置项
const getMapJSON = async (adcode: string = "100000", geoName: string) => {
  const res = await axios.get(
    `https://geo.datav.aliyun.com/areas_v2/bound/${adcode}_full.json`
  );

  // 重新注册地图
  echarts.registerMap(geoName, <any>res.data);
  // 过滤json数据

  const mapData = res.data.features.map((item: any) => {
    return {
      value: item.properties,
      name: item.properties.name,
    };
  });

  return mapData;
};
// 图表生成配置项
const getOption = (geoName: string, mapData: any) => {
  // 图表配置项
  const option = {
    geo3D: {
      zlevel: -100,
      show: true,
      map: geoName, // 地图类型。echarts-gl 中使用的地图类型同 geo 组件相同
      regionHeight: 2,
      shading: "realistic",
      realisticMaterial: {
        detailTexture: "./1.png",
      },
      itemStyle: {
        borderWidth: 1.5,
        borderColor: "#5FB9DA",
        color: "#6597D0",
        opacity: 1,
      },
      label: {
        show: true, // 是否显示标签。
        textStyle: {
          color: "#fff", // 地图初始化区域字体颜色
          fontSize: 40,
        },
        formatter: (e: any) => {
          return ` ${e.name} `;
        },
      },
    },
    series: [
      {
        zlevel: -10,
        regionHeight: 2,
        type: "map3D",
        map: geoName, // 地图类型。echarts-gl 中使用的地图类型同 geo 组件相同
        data: mapData, //这里比较重要:获得过滤后的data,这样点击事件时就能获得这个data的值
        emphasis: {
          label: { show: false },
          itemStyle: {
            color: "transparent",
          },
        },
        shading: "realistic",
        realisticMaterial: {
          detailTexture: "./4.png",
          textureTiling: 2,
        },
        itemStyle: {
          color: "transparent",
        },
      },
    ],
  };
  return option;
};

/**
 * 返回上级地图功能
 */

type HistoryData = {
  name: string;
  adcode: string | undefined;
};
// 地图下钻历史记录
const historyMapData = ref<HistoryData[]>([{ name: "map", adcode: "100000" }]);
// 返回上级地图
const backMap = () => {
  const myChart = echarts.init(
    <HTMLElement>document.getElementById("mapEchart")
  );
  // 去除当前的地图信息
  historyMapData.value.pop();
  const len = historyMapData.value.length;
  // 获取上一级的地图信息
  const newdata = historyMapData.value[len - 1];
  // 重新渲染地图
  initMap(myChart, newdata?.name || "map", newdata?.adcode || "100000");
};

/**
 * 生命周期
 */
onMounted(() => {
  // 挂载echart
  chartMap();
});
</script>

<style scoped>
.investment-screen {
  background-color: rgb(0, 0, 42);
  width: 100vw;
  height: 100vh;
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
}

.map-chart {
  width: 80%;
  height: 80%;
}
</style>

细节讲解

  • 地图配置getOption函数中,使用了双地图geo3Dmap3D两种类型,因为map3D更友好的支持点击事件,所以为了实现点击下钻的功能,我把map3D的视图层级往上提升了,并且透明化了map3D每一块区域的颜色

map3D单独配置时:

这么做就是为了完成:“鼠标移入相关地区区域时高亮展示红框立体区域内容”的需求

image.png
而展示给用户的3d地图是由geo3D渲染的:
image.png

  • geo3D配置详解:

三维图形的着色效果
realistic 真实感渲染
在使用自定义渲染时,材质贴图一定要放到 pubic文件夹 中,否则echarts无法识别。应该是底层echarts打包的时候自己做的处理。

shading: "realistic",
      realisticMaterial: {
        detailTexture: "./1.jpeg",
        roughness: 0.2,
        metalness: 0,
      },
  • map3D配置详解:

配置鼠标移入时的图标,可以自定义更换 image: "./2.png"

emphasis: {
          label: {
            show: true,
            textStyle: {
              color: "#f8fbfb",
              // borderColor: "#17E8F4",
              fontSize: 18,
              padding: [20, 20],
              backgroundColor: {
                image: "./2.png",
              },
            },
          },
          itemStyle: {
            color: "#18B6FE",
          },
        },

总结

本文中地图下钻返回上一级地图的整体功能需求基本完善。

  • 对于新增功能待完善的:

高亮显示区域这个功能,会阻碍鼠标移入时的样式展示,所以每次鼠标移入时,都要清除regionsSetInterVal这个定时器,那么导致定时器清除动画不会播放。
解决方案:鼠标移出时应该重新开始这个计时器,并且要添加防抖,提升性能。(待完成)

  • 可拓展的新功能:

添加动态3d柱状图 (已完成-github项目启动后访问路径:“/Vue3Point” 或者 点击“城市消费水平”的内容,待使用柏林噪声优化柱状图分布)
添加动态3d散点图
添加动态3d折线图
。。。等等功能待开发

  • 15
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 29
    评论
Vue3中实现echarts地图三级的方法如下: 1. 首先,导入所需的地图数据和echarts库。 ```javascript import cityMap from "../../../assets/map/china-main-city-map.js"; import echarts from "echarts"; ``` 2. 在Vue组件的方法中,创建一个函数来渲染echarts地图,并实现地图的功能。 ```javascript methods: { renderMap() { // 创建echarts实例 const chart = echarts.init(document.getElementById("map-container")); // 地图配置项 const options = { series: [ { type: "map", map: "china", label: { show: true, }, data: [ { name: "北京", value: 100 }, { name: "上海", value: 200 }, // 其他省市数据... ], emphasis: { label: { show: true, }, }, }, ], }; // 地图点击事件 chart.on("click", (params) => { const { name } = params; // 判断是否有下级地图数据 if (cityMap[name]) { // 清空原有的地图实例 chart.clear(); // 设置下级地图配置项 options.series<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [【vueEcharts3D地图](https://blog.csdn.net/m0_68324632/article/details/130133913)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [echarts地图省市区三级下联动](https://download.csdn.net/download/u013254183/12309294)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [详解vue中使用echarts地图实现上的可视化 三级下 省>市>县](https://blog.csdn.net/weixin_45419441/article/details/108385368)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值