目录

前端大屏展示可视化-地图的绘制天地图

前端大屏展示可视化-地图的绘制(天地图)

https://i-blog.csdnimg.cn/direct/ded22df47da74cd38b778ea3b7b207a4.png

1、引入

天地图采用CDN方式引入,在引入之后可以直接使用(需要申请密钥,使用大写的T作为命名空间)

<script src="http://api.tianditu.gov.cn/api?v=4.0&tk=您的密钥" type="text/javascript"></script>

2、使用

2.1、初始化

注意天地图使用的是CGCS2000坐标系,与其他地图混用时主要要进行转换

首先要准备一个定宽定高的容器

<div id="chartMap" style="height: 100%;width: 100%;"></div>

获取节点并初始化

// 地图实例
let TDMap = null, TDMapMarkers = null, TDMapMarker = {}, TDMapInfoWindow = {}, TDMapOverLay = {};
// 多边形多环关联表
const ManyTDMapOverLay = new Map();
// 初始化地图对象
if(!TDMap) TDMap = new T.Map("chartMap");

设置中心点以及缩放级

// 设置显示地图的中心点和级别
TDMap.centerAndZoom(new T.LngLat(lng, lat), 12));

3、销毁天地图

// 销毁天地图
const destructionTMap = () => {
  if (TMap.value) {
    TMap.value = null;
    // 直接将节点给删掉
    const parentEl = document.getElementById('mainMap');
    const cahildrenEl = document.getElementById('chartMap');
    if(cahildrenEl) parentEl.removeChild(cahildrenEl);
    // 然后再手动将节点加进来
    const newCahildrenEl = document.createElement("div");
    newCahildrenEl.id = 'chartMap'
    newCahildrenEl.style = 'height: 100%;width: 100%;'
    parentEl.appendChild(newCahildrenEl)
  }
}

4、加入类

geoJSON数据可通过接口获取,或自行 保存到本地,自行引入,建议通过接口获取

4.1、加入多边形

参数一为多边形经纬度,参数二为配置项

new T.Polygon(points, {

color: “blue”, weight: 3, opacity: 1, fillColor: “#FFFFFF”, fillOpacity: 0.3, lineStyle: ‘dashed’

})

<script setup>
  import { onMounted, watch, inject, onBeforeUnmount } from 'vue';
  // 经纬度转换
  import { transformGCJ2WGS } from "@/function/lib/transformGCJ2WGS.js";
  // 生成uuid
  import { uuid } from "@/function/lib"

  defineOptions({name: ''});
  let geoJSON = null;
  const props = defineProps({})
  const emits = defineEmits(['TMapClick']);
  const isIncludeSub = inject('isIncludeSub');
  const mapParams = inject('mapParams');

  // 地图实例
  let TDMap = null, TDMapOverLay = {};
  // 多边形多环关联表
  const ManyTDMapOverLay = new Map();
  async function loadGoJson() {
    geoJSON = await fetch(`https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json`).then(res => res.json()).then(data => {
      return data;
    })
    setTimeout(() => {
      loadTMap()
    }, 500);
  }
  // 加载天地图
  async function loadTMap() {
    if (TDMap) destructionTMap();
    // 中心点,转换坐标
    const centerData = transformGCJ2WGS(Number(geoJSON.features[0].properties.centroid[1] || 27.9937307619152), Number(geoJSON.features[0].properties.centroid[0] || 120.69941136528779));
    const lat = Number(centerData.lat);
    const lng = Number(centerData.lon);
    // 初始化地图对象
    if(!TDMap) TDMap = new T.Map("chartMap");
    const center = new T.LngLat(lng, lat);
    // 设置显示地图的中心点和级别
    TDMap.centerAndZoom(center, 5);
    // 创建一个用于渲染地图事件的方法
    let drawMapFn = (points, adcode, id) => {
      try {
        // 创建面对象
        TDMapOverLay[id] = new T.Polygon(points, {
          color: "blue", weight: 3, opacity: 1, fillColor: "#FFFFFF", fillOpacity: 0.3, lineStyle: 'dashed'
        })
        // 监听面对象移入事件,加入背景色
        TDMapOverLay[id].addEventListener("mouseover", _ => {
          ManyTDMapOverLay.get(adcode).forEach(item => {
            TDMapOverLay[item].setFillColor('rgb(13, 202, 230)');
            TDMapOverLay[item].setFillOpacity(0.6);
          })
          // event.target.setFillColor('rgb(13, 202, 230)');
          // event.target.setFillOpacity(0.6);
        });
        // 监听面对象移出事件,淡化背景色
        TDMapOverLay[id].addEventListener("mouseout", _ => {
          ManyTDMapOverLay.get(adcode).forEach(item => {
            TDMapOverLay[item].setFillColor('#FFFFFF');
            TDMapOverLay[item].setFillOpacity(0.3);
          })
        });
        // 向地图上添加叠加物
        TDMap.addOverLay(TDMapOverLay[id]);
      } catch (error) {
        console.log('error', error);
      }
    }
    // 循环遍历geoJson解析子区域
    geoJSON.features.forEach(geoItem => {
      // 分析coordinates数据若多个数组则表示有多个环,需要创建多个面对象并关联起来
      let coordinates = geoItem.geometry?.coordinates || [];
      const { adcode } = geoItem.properties;
      ManyTDMapOverLay.set(adcode, []);
      // 多环数据需要将多个面对象关联起来(通过code进行关联)
      if(geoItem.geometry.type === 'MultiPolygon') {
        coordinates.forEach((item) => {
          const id = uuid();
          ManyTDMapOverLay.get(adcode).push(id);
          // 多边形经纬度转换
          const points = item[0].map(ele => {
            const latLng = transformGCJ2WGS(ele[1], ele[0]);
            return new T.LngLat(latLng.lon, latLng.lat);
          });
          drawMapFn(points, adcode, id);
        })
      }
      // 单环数据直接创建面对象
      if(geoItem.geometry.type === 'Polygon') {
        const id = uuid();
        ManyTDMapOverLay.get(adcode).push(id);
        // 多边形经纬度转换
        const points = coordinates[0].map(item => {
          const latLng = transformGCJ2WGS(item[1], item[0]);
          return new T.LngLat(latLng.lon, latLng.lat);
        })
        drawMapFn(points, adcode, id);
      }
    })
    drawMapFn = null;
  }

  // 销毁天地图
  const destructionTMap = (addChildren = true) => {
    if (TDMap) {
      TDMap = null;
      // 直接将节点给删掉
      const parentEl = document.getElementById('mainMap');
      const cahildrenEl = document.getElementById('chartMap');
      if(cahildrenEl) parentEl.removeChild(cahildrenEl);
      if(!addChildren) return;
      // 然后再手动将节点加进来
      const newCahildrenEl = document.createElement("div");
      newCahildrenEl.id = 'chartMap'
      newCahildrenEl.style = 'height: 100%;width: 100%;'
      parentEl.appendChild(newCahildrenEl)
    }
  }
  
  onMounted(() => {
    loadGoJson();
  });

  onBeforeUnmount(() => {
    destructionTMap(false);
  })

  // 子组件暴露
  defineExpose({});

</script>

<template>
  <div id="mainMap" style="height: 100%;width: 100%;">
    <div id="chartMap" style="height: 100%;width: 100%;"></div>
  </div>
</template>

<style lang="less" scoped>

</style>

4.2、加入信息窗口

先使用 const TDMapInfoWindow = new T.InfoWindow(); 构建信息窗实例

而后 TDMapInfoWindow.setLngLat(infoWinCenterLatLng); 确定位置

而后 TDMapInfoWindow.setContent(‘html节点’); 加载窗口

最后TDMap.addOverLay(TDMapInfoWindow);加载到天地图上

<script setup>
  import { onMounted, inject, onBeforeUnmount } from 'vue';
  import { transformGCJ2WGS } from "@/function/lib/transformGCJ2WGS.js";
  import { uuid } from "@/function/lib"

  defineOptions({name: ''});
  let geoJSON = null;
  const props = defineProps({})
  const emits = defineEmits(['TMapClick']);
  const isIncludeSub = inject('isIncludeSub');
  const mapParams = inject('mapParams');

  // 地图实例
  let TDMap = null, TDMapInfoWindow = {}, TDMapOverLay = {};
  // 多边形多环关联表
  const ManyTDMapOverLay = new Map();
  async function loadGoJson() {
    geoJSON = await fetch(`https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json`).then(res => res.json()).then(data => {
      return data;
    })
    setTimeout(() => {
      loadTMap()
    }, 500);
  }
  // 加载天地图
  async function loadTMap() {
    if (TDMap) destructionTMap();
    // 中心点,转换坐标
    const centerData = transformGCJ2WGS(Number(geoJSON.features[0].properties.centroid[1] || 27.9937307619152), Number(geoJSON.features[0].properties.centroid[0] || 120.69941136528779));
    const lat = Number(centerData.lat);
    const lng = Number(centerData.lon);
    // 初始化地图对象
    if(!TDMap) TDMap = new T.Map("chartMap");
    const center = new T.LngLat(lng, lat);
    // 设置显示地图的中心点和级别
    TDMap.centerAndZoom(center, mapParams.areaCode === '100000' ? 5 : (isIncludeSub.value ? 9 : 12));
    // 创建一个用于渲染地图事件的方法
    let drawMapFn = (geoItem, points, name, adcode, id) => {
      try {
        // 创建面对象
        TDMapOverLay[id] = new T.Polygon(points, {
          color: "blue", weight: 3, opacity: 1, fillColor: "#FFFFFF", fillOpacity: 0.3, lineStyle: 'dashed'
        })
        // 监听面对象移入事件,加入背景色以及信息窗口
        TDMapOverLay[id].addEventListener("mouseover", _ => {
          ManyTDMapOverLay.get(adcode).forEach(item => {
            TDMapOverLay[item].setFillColor('rgb(13, 202, 230)');
            TDMapOverLay[item].setFillOpacity(0.6);
          })
          const list = getTopmostVertex(name === '内蒙古自治区' ? geoItem.geometry.coordinates[0] : geoItem.geometry.coordinates[0][0]);
          const targetLatLng = transformGCJ2WGS(list[1], list[0]);
          // 信息窗口
          const infoWinCenterLatLng = new T.LngLat(targetLatLng.lon, targetLatLng.lat);
          TDMapInfoWindow[adcode] = new T.InfoWindow();
          TDMapInfoWindow[adcode].setLngLat(infoWinCenterLatLng);
          TDMapInfoWindow[adcode].setContent(
            '<div style="color: #000;text-align: left;font-size: 18px;line-height: 10px;">'
            + '<p style="font-weight: bold;line-height: 10px;">' + name + '</p>'
          );
          TDMap.addOverLay(TDMapInfoWindow[adcode]);
        });
        // 监听面对象移出事件,淡化背景色以及关闭信息窗口
        TDMapOverLay[id].addEventListener("mouseout", _ => {
          ManyTDMapOverLay.get(adcode).forEach(item => {
            TDMapOverLay[item].setFillColor('#FFFFFF');
            TDMapOverLay[item].setFillOpacity(0.3);
          })
          TDMapInfoWindow[adcode].closeInfoWindow();
        });
        // 向地图上添加叠加物
        TDMap.addOverLay(TDMapOverLay[id]);
      } catch (error) {
        console.log('error', error);
      }
    }
    // 循环遍历geoJson解析子区域
    geoJSON.features.forEach(geoItem => {
      // 分析coordinates数据若多个数组则表示有多个环,需要创建多个面对象并关联起来
      let coordinates = geoItem.geometry?.coordinates || [];
      const {name, adcode} = geoItem.properties;
      ManyTDMapOverLay.set(adcode, []);
      // 多环数据需要将多个面对象关联起来(通过code进行关联)
      if(geoItem.geometry.type === 'MultiPolygon') {
        coordinates.forEach((item) => {
          const id = uuid();
          ManyTDMapOverLay.get(adcode).push(id);
          // 多边形经纬度转换
          const points = item[0].map(ele => {
            const latLng = transformGCJ2WGS(ele[1], ele[0]);
            return new T.LngLat(latLng.lon, latLng.lat);
          });
          drawMapFn(geoItem, points, name, adcode, id);
        })
      }
      // 单环数据直接创建面对象
      if(geoItem.geometry.type === 'Polygon') {
        const id = uuid();
        ManyTDMapOverLay.get(adcode).push(id);
        // 多边形经纬度转换
        const points = coordinates[0].map(item => {
          const latLng = transformGCJ2WGS(item[1], item[0]);
          return new T.LngLat(latLng.lon, latLng.lat);
        })
        drawMapFn(geoItem, points, name, adcode, id);
      }
    })
    drawMapFn = null;
  }

  // 计算顶点坐标
  function getTopmostVertex(coordinates) {
    let topmostVertex = null;
    let maxLatitude = -Infinity; // 初始化最大纬度为负无穷大
    // 遍历坐标数组来找到最大纬度值
    for (const vertex of coordinates) {
      const latitude = vertex[1]; // 纬度是坐标数组的第二个元素
      if (latitude > maxLatitude) {
        maxLatitude = latitude;
        topmostVertex = vertex;
      }
    }
    return topmostVertex;
  }

  // 销毁天地图
  const destructionTMap = (addChildren = true) => {
    if (TDMap) {
      TDMap = null;
      // 直接将节点给删掉
      const parentEl = document.getElementById('mainMap');
      const cahildrenEl = document.getElementById('chartMap');
      if(cahildrenEl) parentEl.removeChild(cahildrenEl);
      if(!addChildren) return;
      // 然后再手动将节点加进来
      const newCahildrenEl = document.createElement("div");
      newCahildrenEl.id = 'chartMap'
      newCahildrenEl.style = 'height: 100%;width: 100%;'
      parentEl.appendChild(newCahildrenEl)
    }
  }
  
  onMounted(() => {
    loadGoJson();
  });

  onBeforeUnmount(() => {
    destructionTMap(false);
  })

  // 子组件暴露
  defineExpose({});

</script>

<template>
  <div id="mainMap" style="height: 100%;width: 100%;">
    <div id="chartMap" style="height: 100%;width: 100%;"></div>
  </div>
</template>

<style lang="less" scoped>

</style>