vue3中结合Echarts实现中国地图及城市下钻

<template>
  <div id="myMap" ref="myMap"></div>
  <div
    class="backParent"
    v-show="currentadcode != 100000"
    @click="returnLastMap(currentMap?.parentadcode)"
  >
    返回
  </div>
</template>

<script setup>
import * as echarts from "echarts";
// import mapdata from "./city-data.json";
import { onMounted, ref, watch, getCurrentInstance } from "vue";
const { proxy } = getCurrentInstance();
const { $axios } = proxy;

// 定义当前所有的地图
let allMap = new Map();

// 当前地图
let currentMap = ref(null);
// echarts实例
let myChart,
  currentadcode = ref(100000);
const init = () => {
  allMap.set(100000, {
    name: "中国",
    adcode: 100000,
    url: "https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json",
    childrenNum: 34,
    center: [0, 0],
    hasRegister: false, // 是否已经注册在echarts
  });
  currentMap.value = allMap.get(currentadcode.value);
  myChart = echarts.init(document.getElementById("myMap"));
  // renderChart(currentMap.value, data, dataMap);
  renderChart(currentMap.value);
  // 图表跟随屏幕自适应
  window.addEventListener("resize", () => {
    myChart.resize();
  });
  // 地图点击事件
  myChart.on("click", (params) => {
    let n = getMapKey(params.name, allMap);
    if (allMap.get(n)?.childrenNum == 0) return;
    currentadcode.value = n;
  });
};
// 根据map中数值,获取key
const getMapKey = (value, map) => {
  let arriterator = map.values(),
    res = 0;
  for (const iterator of arriterator) {
    if (iterator.name == value) {
      res = iterator.adcode;
      break;
    }
  }
  // console.log(res);
  return res;
};
function getCurrentadcode(mapdata) {
  let currentMap = new Map();

  mapdata.features.map((item) => {
    if (item.properties.name != "") {
      let cityinfo = {
        name: item.properties.name,
        adcode: item.properties.adcode,
        childrenNum: item.properties.childrenNum,
        url: `https://geo.datav.aliyun.com/areas_v3/bound/${item.properties.adcode}_full.json`,

        center: item.properties.center,
        parentadcode: item.properties.parent?.adcode,
        hasRegister: false,
      };
      currentMap.set(cityinfo.adcode, cityinfo);
    }
  });
  return currentMap;
}
// 根据城市名称name
function getCurrentadcodebyname(mapdata) {
  let currentMap = new Map();

  mapdata.features.map((item) => {
    if (item.properties.name != "") {
      let cityinfo = {
        name: item.properties.name,
        adcode: item.properties.adcode,
        childrenNum: item.properties.childrenNum,
        url: `https://geo.datav.aliyun.com/areas_v3/bound/${item.properties.adcode}_full.json`,
        center: item.properties.center,
        parentadcode: item.properties.parent?.adcode,
        hasRegister: false,
      };
      currentMap.set(cityinfo.name, cityinfo);
    }
  });
  return currentMap;
}
// 获取地图json, 绘制地图
// const renderChart = async (cMap, dataArr, dataMap) => {
const renderChart = async (cMap) => {
  // myChart.showLoading(); // 加载动画
  // 访问当前的地图数据
  let { data: mapdata } = await $axios.get(cMap?.url);
  let currentName = cMap?.name;

  // 判断是否注册过
  if (!cMap?.hasRegister) {
    echarts.registerMap(currentName, mapdata);
    // 当前地图下的地区信息
    let currentCityMap = getCurrentadcode(mapdata);

    allMap = new Map([...allMap, ...currentCityMap]);
    allMap.get(cMap?.adcode).hasRegister = true;
  }

  let option = {
    tooltip: {
      position: "right",
      color: "#F7C034",
      formatter(d) {
        // console.log(d);
        return `<div style="padding: 5px 10px;">${d.name}:${
          d?.data?.value || 0
        }</div>`;
      },
    },
    title: {
      text: `${currentName}地图`,
      left: "center",
      top: "2%",
      textStyle: {
        color: "#000",
      },
    },
    //热力图配置
    visualMap: {
      left: "left",
      orient: "vertical",
      itemWidth: 10,
      min: 0,
      max: 1000,
      align: "center",
      bottom: "10%",
      inRange: {
        color: [
          "#313695",
          "#4575b4",
          "#74add1",
          "#abd9e9",
          "#e0f3f8",
          "#ffffbf",
          "#fee090",
          "#fdae61",
          "#f46d43",
          "#d73027",
          "#a50026",
        ],
      },
      calculable: true,
    },
    //层级地图配置
    series: [
      {
        name: `${currentName}地图`,
        map: currentName,
        type: "map",
        roam: true,
        label: {
          normal: {
            formatter(d) {
              return `${d.name}`;
            },
            show: true,
            textStyle: {
              color: "#fff",
            },
          },
          emphasis: {
            show: true,
            textStyle: {
              color: "#05C3F9",
            },
          },
        },
        itemStyle: {
          normal: {
            areaColor: "#3D8CFD",
            borderColor: "#5EC9F9",
            borderWidth: 1,
          },
          emphasis: {
            areaColor: "#0C356C",
            shadowColor: "#1773c3",
            shadowBlur: 20,
          },
        },
        // markPoint: {
        //   symbol: "circle",
        //   itemStyle: {
        //     color: "#F7C034",
        //     // borderColor:'#000'
        //   },
        //   label: {
        //     normal: {
        //       show: true,
        //     },
        //     emphasis: {
        //       show: true,
        //     },
        //   },
        //   // data: dataArr,
        //   data: [
        //     {
        //       name: "广东省",
        //       coord: [20, 20],
        //     },
        //   ],
        //   blur: {},
        // },
        // data: dataMap,
        data: [
          {
            name: "北京市",
            value: 100,
          },
          {
            name: "上海市",
            value: 80,
          },
          {
            name: "广东省",
            value: 120,
          },
          {
            name: "黑龙江省",
            value: 10,
          },
          {
            name: "台湾省",
            value: 100,
          },
        ],
      },
    ],
  };
  myChart.clear();
  myChart.setOption(option, true);
};
onMounted(() => {
  init();
});
// 监听currentadcode地图值
watch(currentadcode, async (newval, oldval) => {
  let nextMap = allMap.get(newval);
  // 如果存在子节点
  if (nextMap?.childrenNum && nextMap.childrenNum > 0) {
    currentMap.value = nextMap;
    if (currentMap.value.parentadcode == undefined) {
      currentMap.value.parentadcode = oldval;
    }
    // console.log("nextMap: ", nextMap);
    // if (nextMap.adcode != 100000) {
    //   query.code = nextMap.adcode;
    //   queryData.code = nextMap.adcode;
    // } else {
    //   delete query.code;
    //   queryData.code = "";
    // }
    // const data = await getDeptList();
    // const dataMap = await getDeptHotMap();
    // renderChart(nextMap, data, dataMap);
    renderChart(nextMap);
  }
});
// 返回上级地图
const returnLastMap = (adcode) => {
  currentadcode.value = adcode;
};
</script>

<style lang='scss' scoped>
/* 这里是组件的样式 */
#myMap {
  width: 100%;
  height: 600px;
}
</style>

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值