echart5.x地图下钻和地图标点(vue3+ts)

地图下钻的独立组件,引入即用
在echart地图上踩了太多坑了,记录下吧

使用:

<CityMap :list="mapList" @params="changeParams" />

// 地图标点
let mapList = [
  {
    FarmID: "337207bb-5abe-42ea-949c-e034a3ae6377",
    FarmName: "优然牧场一场",
    Long: 119.23944,
    Lati: 34.324724,
    Admin: "小王",
    Tel: "",
    Livestock: 7660,
    Address: "",
  },
];
let changeParams = (val: any) => {
  console.log("地图会传的数据:", val);
};

组件代码:

<template>
  <div class="cityMap">
    <div class="backMap" :class="{ notAllowed: !notAllowed }" @click="backMap">
      <span>返回</span>
    </div>
    <div class="tradeIn-cattle-map" ref="echartsRef"></div>
  </div>
</template>

<script setup lang="ts">
/**
 * 省市区-地图下钻
 */
import * as echarts from "echarts";
import {
  ref,
  onMounted,
  reactive,
  Ref,
  onUnmounted,
  nextTick,
  watch,
} from "vue";
import axios from "axios";
import { mapScatter } from "@/utils/youran";
// 本地测试用的地图json数据
const mapDatas = require("./320700_full.json");
const mapDatas2 = require("./320723.json");
const echartsRef: Ref = ref(null);

let notAllowed = ref<Boolean>(false);

let timeFn: any = null;

let myChart: any = null;

// 所有地图
let AllMap = reactive([
  {
    prefix: "",
    adcode: "",
    name: "",
  },
]);

onMounted(() => {
  initChart();
});

onUnmounted(() => {});

// 获取地图--和域名一样的地图(上线上上去,防跨域)
function GetMapGeoJson(cityCN: string, citylevel: string) {
  var uploadedDataURL = "";
  if (citylevel == "china") {
    //全国地图
    return "/YooHooMIS/Scripts/echarts/china/100000_full.json";
  }
  if (citylevel != "district" && (cityCN + "").substring(4) != "00")
    citylevel = "district";
  if (citylevel == "district") {
    uploadedDataURL =
      "/YooHooMIS/Scripts/echarts/china/district/" +
      cityCN +
      ".json";
  } else if (citylevel == "city") {
    uploadedDataURL =
      "/YooHooMIS/Scripts/echarts/china/city/" +
      cityCN +
      "_full.json";
  } else {
    uploadedDataURL =
      "/YooHooMIS/Scripts/echarts/china/province/" +
      cityCN +
      "_full.json";
  }
  return uploadedDataURL;
}

// 地图2--阿里云地图
function GetMapGeoJson2(cityCN: string, citylevel: string) {
  var uploadedDataURL = "";
  if (citylevel == "china") {
    //全国地图
    return "https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json";
  }
  if (citylevel != "district" && (cityCN + "").substring(4) != "00")
    citylevel = "district";
  if (citylevel == "district") {
    uploadedDataURL =
      "https://geo.datav.aliyun.com/areas_v3/bound/" + cityCN + ".json";
  } else if (citylevel == "city") {
    uploadedDataURL =
      "https://geo.datav.aliyun.com/areas_v3/bound/" + cityCN + "_full.json";
  } else {
    uploadedDataURL =
      "https://geo.datav.aliyun.com/areas_v3/bound/" + cityCN + "_full.json";
  }
  return uploadedDataURL;
}

// 向外传值
const emit = defineEmits(["params"]);

function returnParams(params: object) {
  emit("params", params);
}

const props = defineProps({
  funType: {
    type: Object,
    default: {},
  },
  list: {
    type: Array,
    default: [],
  },
});

//各省份的数据--本地图是标点图,所以不需要了,废弃了这里
let allData: any = reactive([]);
function initMapData() {
  // Api.getMapData({
  //   funType: props.funType.module,
  //   mapData: JSON.stringify(AllMap),
  //   range: props.funType.range,
  // }).then((res) => {
  // allData.length = 0;
  // allData.push(
  //   ...[
  //     {
  //       prefix: "district",
  //       adcode: "320703",
  //       name: "连云区",
  //       value: "0",
  //     },
  //     {
  //       prefix: "district",
  //       adcode: "320707",
  //       name: "赣榆区",
  //       value: "0",
  //     },
  //     {
  //       prefix: "district",
  //       adcode: "320722",
  //       name: "东海县",
  //       value: "0",
  //     },
  //     {
  //       prefix: "district",
  //       adcode: "320706",
  //       name: "海州区",
  //       value: "0",
  //     },
  //     {
  //       prefix: "district",
  //       adcode: "320723",
  //       name: "灌云县",
  //       value: "0",
  //     },
  //     {
  //       prefix: "district",
  //       adcode: "320724",
  //       name: "灌南县",
  //       value: "0",
  //     },
  //   ]
  // );
  // console.log("AllMap", AllMap);
  // console.log("各省份的数据allData", allData);

  setTimeout(() => {
    setOption();
  }, 1);
  // });
}

watch(
  [() => props, AllMap],
  (val, val2) => {
    initMapData();
  },
  {
    deep: true,
  }
);

// 激活地图栈

// 当前激活地图
let defaultMap = reactive({
  prefix: "",
  adcode: "",
  name: "",
});

//  初始化地图
initData();

function initData() {
  defaultMap = {
    prefix: "city",
    adcode: "320700",
    name: "连云港市",
  };
}

/**
 获取对应的json地图数据,然后向echarts注册该区域的地图,最后加载地图信息
 @params {String} mapCode:json数据的地址
 @params {String} name: 地图名称
 */
let mapStack: any[] = [];

function loadMap() {
  if (mapStack.length == 0) {
    mapStack.push(defaultMap);
  }
  let mapData = GetMapGeoJson2("320700", "city") || mapDatas;

  if (mapStack.length > 1) {
    mapData = GetMapGeoJson2(
      mapStack[mapStack.length - 1].adcode,
      mapStack[mapStack.length - 1].prefix
    );
  }
  AllMap = [
    {
      prefix: "district",
      adcode: "320703",
      name: "连云区",
    },
    {
      prefix: "district",
      adcode: "320707",
      name: "赣榆区",
    },
    {
      prefix: "district",
      adcode: "320722",
      name: "东海县",
    },
    {
      prefix: "district",
      adcode: "320706",
      name: "海州区",
    },
    {
      prefix: "district",
      adcode: "320723",
      name: "灌云县",
    },
    {
      prefix: "district",
      adcode: "320724",
      name: "灌南县",
    },
  ];
  // 注册当前激活地图
  // console.log("激活地图", mapStack[mapStack.length - 1].name, mapData);
  axios.get(mapData).then((geoJson: any) => {
    echarts.registerMap(mapStack[mapStack.length - 1].name, geoJson.data);
    nextTick(() => {
      setOption();
    });
  });
}

function setOption() {
  let option = {
    tooltip: {
      show: true,
      className: "CityMapChartTooltipBg",
      formatter: (params: any) => {
        if (params.componentSubType === "scatter") return params.name;
      },
    },
    geo: {
      map: mapStack[mapStack.length - 1].name || "连云港市",
      itemStyle: {
        normal: {
          areaColor: `#10359b`,
          borderColor: `#fff`,
          borderWidth: 1,
          shadowColor: `#94d9ff`,
          shadowOffsetX: -4,
          shadowOffsetY: 8,
          shadowBlur: 1,
        },
        emphasis: {
          label: {
            show: false,
          },
        },
      },
    },
    xAxis: [],
    yAxis: [],
    series: [
      {
        name: "MAP",
        type: "map",
        map: mapStack[mapStack.length - 1].name || "连云港市",
        selectedMode: "false", //是否允许选中多个区域
        label: {
          normal: {
            show: true,
            textStyle: {
              color: "#fff",
              fontSize: 16,
              fontFamily: "SourceHanSansCN",
            },
          },
        },

        itemStyle: {
          areaColor: "#0f18c2",
          borderColor: "#6becf5",
          borderWidth: 1.5,
          emphasis: {
            show: true,
            areaColor: "#55ade8", // 鼠标悬浮地图面的颜色
            shadowColor: "#94d9ff",
            shadowOffsetX: -2,
            shadowOffsetY: 2,
            shadowBlur: 5,
            label: {
              show: true,
              textStyle: {
                color: "#fff",
                fontSize: 16,
                fontFamily: "SourceHanSansCN",
              },
            },
          },
        },
        // data: allData,//各省的数据,鼠标放上显示,现在是标点图所以不显示
      },
    ],
  };
  addScatter(option);
  myChart.setOption(option);
}
// 加牧场坐标点
function addScatter(option: any) {
  let dataList: any = [];
  if (props.list.length > 0) {
    props.list.forEach((item: any) => {
      let name = `
      <div class="CityMapChartTooltipBgBox">
        <div class="list">
          <div class="item">
            <span>${item.FarmName || ""}:</span>
            <span>${item.Livestock || 0}头</span>
          </div>
          <div class="item">
            <span>负责人:</span>
            <span>${item.Admin || ""}</span>
          </div>
          <div class="item">
            <span>地址:</span>
            <span>${item.address || ""}</span>
          </div>
        </div>
      </div>
    `;
      dataList.push({
        name: name,
        value: [item.Long, item.Lati],
      });
    });
  }
  option.series.push({
    type: "scatter",
    coordinateSystem: "geo",
    symbol: "image://" + mapScatter,
    symbolSize: [66, 36],
    itemStyle: {
      normal: {
        color: "#1cedd4",
        shadowBlur: 10,
        shadowColor: "#333",
      },
    },
    zlevel: 2,
    data: dataList,
  });
}

let initChart = () => {
  if (!myChart) {
    myChart = echarts.init(echartsRef.value);
  }
  loadMap();

  //单击切换到省级地图,当mapCode有值,说明可以切换到下级地图
  myChart.on("click", (params: any) => {
    notAllowed.value = true;
    clearTimeout(timeFn);
    //由于单击事件和双击事件冲突,故单击的响应事件延迟250毫秒执行
    timeFn = setTimeout(() => {
      let clickMap = AllMap.find((item) => item.name == params.name);
      // if (!clickMap) {
      //   alert("无此区域地图显示");
      //   return;
      // }
      // 向外传参
      returnParams(clickMap || {});
      // 只存3级
      if (mapStack.length < 3) {
        mapStack.push(clickMap);
      }
      loadMap();
    }, 250);
  });

  // 绑定双击事件,返回全国地图
  myChart.on("dblclick", (params: any) => {
    //当双击事件发生时,清除单击事件,仅响应双击事件
    clearTimeout(timeFn);

    // 以防初始化双击丢栈
    if (mapStack.length > 1) {
      mapStack.pop();
    }
    let res = mapStack[mapStack.length - 1];
    //返回参数
    returnParams(res);
    loadMap();
  });
};

let backMap = () => {
  notAllowed.value = false; //鼠标放上去的禁用状态
  //当双击事件发生时,清除单击事件,仅响应双击事件
  clearTimeout(timeFn);

  // 取当前默认地图
  returnParams(defaultMap);
  mapStack.length = 0;
  // 地图栈  最后一个
  loadMap();
};
</script>

<style lang="less" scoped>
.cityMap {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;

  .backMap {
    position: absolute;
    top: 0;
    left: 40px;
    border: none;
    z-index: 9;

    span {
      display: block;
      font-size: 12px;
      border-radius: 7px;
      background-color: #06bcec;
      padding: 4px 6px;
      color: #fff;
      cursor: pointer;
    }

    &:focus {
      outline: none;
    }

    &:hover {
      background-size: 100% 100%;

      span {
        color: #ffffff;
      }
    }

    &.notAllowed {
      cursor: not-allowed;
    }
  }

  .tradeIn-cattle-map {
    width: 90%;
    height: 90%;
  }
}
</style>

效果图:

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值