基于Vue3 + ts + echarts(版本5.X)实现中国地图下钻、地图打点、地图热力图功能

写在前面:

实现效果图

基于Vue3 + ts + echarts(版本5.X)实现中国地图下钻、地图打点、地图热力图功能_第1张图片

基于Vue3 + ts + echarts(版本5.X)实现中国地图下钻、地图打点、地图热力图功能_第2张图片

 基于Vue3 + ts + echarts(版本5.X)实现中国地图下钻、地图打点、地图热力图功能_第3张图片

1.比较重要的部分用红字标出

 2.安装echats:       

npm install echarts --save

 3.由于echarts5版本的已经没有自带地图数据了,所以地图数据需要到专门的GEO数据网站中下载。这里提供一个阿里的下载地址:DataV.GeoAtlas地理小工具系列 对于这个工具网站,有一个重点需要说一下

用阿里的JSON API测试没有问题,但是上正式环境,调用他们的JSON API是要花钱的。

解决办法就是,将地图数据json文件全部下载下来。然后按照100000_full.json这种格式,放到你们自己的服务器就可以了

4.功能说明,本次教程内容基于vue3+ts+echarts 5版本,实现的内容包括,中国地图的下钻到省市区县级、在指定经纬度进行打点标记。并在鼠标浮动时展示该点的信息、通过区域点数量,呈现地图热力图。

接下来,正式开始实现。

第一步:建立地图容器,给上宽高,导入echarts。

import * as echarts from "echarts";

第二步:实现过程中需要的类型文件:


export interface Geodatav {
    type:     string;
    features: Feature[];
}

export interface Feature {
    type:       FeatureType;
    properties: Properties;
    geometry:   Geometry;
}

export interface Geometry {
    type:        GeometryType;
    coordinates: Array>>;
}

export enum GeometryType {
    MultiPolygon = "MultiPolygon",
    Polygon = "Polygon",
}

export interface Properties {
    adcode:           number | string;
    name:             string;
    center?:          number[];
    centroid?:        number[];
    childrenNum?:     number;
    level?:           Level;
    parent?:          Parent;
    subFeatureIndex?: number;
    acroutes?:        number[];
    adchar?:          string;
}

export enum Level {
    Province = "province",
}

export interface Parent {
    adcode: number;
}

export enum FeatureType {
    Feature = "Feature",
}

// 城市属性
export interface citymodel {
    name: string,
    adcode: number | string,
    url: string,
    childrenNum: number | undefined,
    center?: number[],
    parentadcode?: number | string,  // 父地图
    hasRegister: boolean  // 是否已经注册在echarts
}

第三步:写一个简单的工具,实现将阿里中国地图城市数据集合JSON数据引入项目中并使用。

// 引入type
import { Feature, Geodatav, citymodel } from "./geodatav";


// 获取当前json下的省份城市区域adcode和json
// 根据城市adcode
function getCurrentadcode(mapdata: Geodatav) {
    let currentMap = new Map();

    mapdata.features.map((item:Feature)=>{
        if (item.properties.name != '') {
            let cityinfo: citymodel = {
                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: Geodatav) {
    let currentMap = new Map();

    mapdata.features.map((item:Feature)=>{
        if (item.properties.name != '') {
            let cityinfo: citymodel = {
                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;
}



export { getCurrentadcode, getCurrentadcodebyname }

注意,在这里,如果你采用将地图数据放在自己的服务器,讲JSON数据下载下来,替换地址即可

第四步:开始渲染地图

首先引入2个工具文件

import * as echarts from "echarts";
import { getCurrentadcode } from "./utils/getAllChineseCity";
import { citymodel } from "./utils/geodatav";

定义地图

const echartsMap1: any = ref(null);
// 定义当前所有的地图
let allMap: Map = new Map();

// 当前地图
let currentMap: Ref = ref(null);
// echarts实例
let myChart: any,
  currentadcode: Ref = ref(100000);

在onMounted中初始化中国地图 

onMounted(async () => {
  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) as citymodel;
  myChart = echarts.init(echartsMap1.value);
  renderChart(currentMap.value, data, dataMap);
  // 图表跟随屏幕自适应
  window.addEventListener("resize", () => {
    myChart.resize();
  });
  // 地图点击事件
  myChart.on("click", (params: any) => {
    let n = getMapKey(params.name, allMap);
    if (allMap.get(n)?.childrenNum == 0) return;
    (currentadcode.value as number | string) = n;
  });
});
// 根据map中数值,获取key
const getMapKey = (
  value: string,
  map: Map
): number | string => {
  let arriterator = map.values(),
    res: number | string = 0;
  for (const iterator of arriterator) {
    if (iterator.name == value) {
      res = iterator.adcode;
      break;
    }
  }
  console.log(res);
  return res;
};

其中data,dataMap为我传入地图中需要渲染的数据。你们可以自信传入你们需要展示的数据。

第五步:监听currentadcode的变化,更新地图

// 监听currentadcode地图值
watch(currentadcode, async (newval, oldval) => {
  let nextMap = allMap.get(newval) as citymodel;
  // 如果存在子节点
  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);
  }
});

绘制地图函数:

// 获取地图json, 绘制地图
const renderChart = async (cMap: citymodel | null, dataArr, dataMap) => {
  // myChart.showLoading(); // 加载动画
  // 访问当前的地图数据
  let { data: mapdata } = await axios.get(cMap?.url as any);
  let currentName = cMap?.name;

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

    allMap = new Map([...allMap, ...currentCityMap]);
    (allMap.get(cMap?.adcode as string | number) as citymodel).hasRegister =
      true;
  }

  let option = {
    tooltip: {
      position: "right",
      color: "#F7C034",
      formatter(d: any) {
        console.log(d);
        return `
${d.name}
`; }, }, title: { text: `${currentName}地图`, left: "center", top: "2%", textStyle: { color: "#fff", }, }, //热力图配置 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: any) { 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, blur: {}, }, data: dataMap, }, ], }; myChart.clear(); myChart.setOption(option, true); };

最后,返回上级地图方法:

// 返回上级地图
const returnLastMap = (adcode: any) => {
  currentadcode.value = adcode;
};

你可能感兴趣的:(vue,echarts,echarts,前端,javascript,vue.js)