vue3使用天地图记录,百度地图改使用天地图

天地图基础

官方网址: 天地图国家地理信息公共服务平台

  1. 登录
    在这里插入图片描述

  2. 创建新应用
    在这里插入图片描述
    在这里插入图片描述

  3. public/index.html
    注:代码内{}表示注释,需连同大括号一起替换

<html lang="">
  <head>
    <script src="http://api.tianditu.gov.cn/api?v=4.0&tk={天地图-应用管理-Key名称}" type="text/javascript"></script>
  </head>
</html>

旧项目改用天地图

历史坐标点会有偏移的原因

坐标点偏移原因:使用坐标系不同

百度地图【百度坐标】(BD-09)
天地图【CGCS2000】(2000国家大地坐标系)
高德地图【GCJ-02】(国家测量局02号标准)

参考链接:
链接1: 简单介绍坐标关系
链接2: 对互联网中常见地图的坐标系探讨

转换方法,百度地图bd09II坐标转换天地图CGCS2000坐标

链接1: 百度地图bd09II坐标转换天地图CGCS2000坐标

import { ElMessage } from 'element-plus';
// 转大地坐标系(传前两个参数表示从百度坐标转,传后两个参数表示从高德坐标转)
export const coordinateTransformation: any = (
  bdLon: number | undefined,
  bdLat: number | undefined,
  marsLon: number | undefined,
  marsLat: number | undefined
) => {
  const mars_point = { lon: 0, lat: 0 };
  if (bdLon && bdLat) {
    const x_pi = (3.141592653589793 * 3000.0) / 180.0;
    //百度坐标转成火星坐标
    const x = bdLon - 0.0065;
    const y = bdLat - 0.006;
    const z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
    const theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
    mars_point.lon = z * Math.cos(theta);
    mars_point.lat = z * Math.sin(theta);
  } else if (marsLon && marsLat) {
    mars_point.lon = marsLon;
    mars_point.lat = marsLat;
  } else {
    ElMessage.warning('coordinateTransformation方法传参错误!');
    return { lng: undefined, lat: undefined };
  }
  //把火星坐标GCJ02转地球坐标系WGS84
  const gcjLon = mars_point.lon;
  const gcjLat = mars_point.lat;
  const d = delta(gcjLon, gcjLat);
  function delta(lon: number, lat: number) {
    const PI = 3.141592653589793;
    const a = 6378245.0;
    const ee = 0.006693421622965943;
    let dLon = transformLon(lon - 105.0, lat - 35.0);
    let dLat = transformLat(lon - 105.0, lat - 35.0);
    const radLat = (lat / 180.0) * PI;
    let magic = Math.sin(radLat);
    magic = 1 - ee * magic * magic;
    const sqrtMagic = Math.sqrt(magic);
    dLon = (dLon * 180.0) / ((a / sqrtMagic) * Math.cos(radLat) * PI);
    dLat = (dLat * 180.0) / (((a * (1 - ee)) / (magic * sqrtMagic)) * PI);
    return {
      lon: dLon,
      lat: dLat,
    };
  }
  function transformLon(x: number, y: number) {
    const PI = 3.141592653589793;
    let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
    ret += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
    ret += ((20.0 * Math.sin(x * PI) + 40.0 * Math.sin((x / 3.0) * PI)) * 2.0) / 3.0;
    ret += ((150.0 * Math.sin((x / 12.0) * PI) + 300.0 * Math.sin((x / 30.0) * PI)) * 2.0) / 3.0;
    return ret;
  }
  function transformLat(x: number, y: number) {
    const PI = 3.141592653589793;
    let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
    ret += ((20.0 * Math.sin(6.0 * x * PI) + 20.0 * Math.sin(2.0 * x * PI)) * 2.0) / 3.0;
    ret += ((20.0 * Math.sin(y * PI) + 40.0 * Math.sin((y / 3.0) * PI)) * 2.0) / 3.0;
    ret += ((160.0 * Math.sin((y / 12.0) * PI) + 320 * Math.sin((y * PI) / 30.0)) * 2.0) / 3.0;
    return ret;
  }

  return {
    lng: gcjLon - d.lon,
    lat: gcjLat - d.lat,
  };
};

边框线

在天地图官方文档中,服务类-行政区划接口返回有:“points”(行政区划范围),但目前实际测试中并没有返回,所以通过一下三种方法设置边缘线。

svg(需要设计人员帮助)

所需数据来源:DataV.GeoAtlas(高德地图)

  1. 下载svg图片,找设计人员帮忙把svg图片截取一下,移除多余的空白部分。
    处理前

  2. 处理后的图片导入项目
    处理后(对线条颜色也做了调整)

  3. 设置svg背景图

function setSVG() {
  let imgURL = require('@/assets/img/chinamap.svg');
  var bd = new T.LngLatBounds(new T.LngLat(bounds[0], bounds[1]), new T.LngLat(bounds[2], bounds[3]));
  let img = new T.ImageOverlay(imgURL, bd, {
    opacity: 1,
    alt: '中国',
  });
  tdtMap.value.addOverLay(img);
}

json转化

所需数据来源:DataV.GeoAtlas(高德地图)

  1. 下载json文件
  2. 调用下面的方法
  3. 将控制台打印的结果拷贝保存到项目中
import { datavJson } from './datavJson';
/**
 * 新项目通过这个方法将datav获取的边框线转为天地图坐标线,只需要运行一次,会将转化后的结果打印在控制台
 * datavJson:datav拷贝下来的数据
 * logList:转化后的结果,格式应为:
 * [
 *   [
 *     [点lng,点lat], // 单个点
 *     [点lng,点lat]
 *   ], // 一条线
 *   ……
 * ]
 */
export const getTransformRes: any = () => {
  const logList: any = [];
  datavJson.features.map((el) => {
    el.geometry.coordinates.map((coordinatesItem) => {
      coordinatesItem.map((lineItem) => {
        const line: any = [];
        lineItem.map((point) => {
          const pointObj = coordinateTransformation(undefined, undefined, point[0], point[1]);
          line.push([pointObj.lng, pointObj.lat]);
        });
        logList.push(line);
      });
    });
  });
  console.log(logList);
};

bigemap网站获取(可以获取街道数据)

参考文档1:https://blog.csdn.net/weixin_44861708/article/details/114223258
参考文档2:https://www.yuucn.com/a/1565092.html

所需数据来源:
kml文件:http://www.bigemap.com/reader/download/
转geojson:http://www.bigemap.com/reader/download/

展示页完整示例代码(中国范围,后端接口提供每个省相关信息)

效果展示

<template>
  <div ref="tdtMapRef" class="divTdtMap"></div>
  <div ref="infoRef" class="infoDiv" v-show="currentWindow.title">
    <div class="title">{{ currentWindow.title }}</div>
    <div class="contentDiv">弹框详细信息:{{ currentWindow.detail }}</div>
  </div>
</template>
<script lang="ts" setup>
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue';
import { GetMapDataApi } from '@/api/mapData';
import { AnyObject } from '@/types/common';

// 获取接口参数
const unitguid = route.query.unitguid as string;
const tdtMap: any = ref({});
const tdtMapRef = ref(); // 地图
const infoRef = ref(); // 弹框内容
let T = (window as any).T;
let infoWin = new T.InfoWindow();
let administrative = new T.AdministrativeDivision();
let markerIcon = new T.Icon({
  iconUrl: require(`@/assets/icon/map_icon.png`), // 自定义标记点图标
  iconSize: new T.Point(25, 41), // 标记图标大小
  iconAnchor: new T.Point(12, 41), // 标记图标箭头位置
});
// 窗口信息
let currentWindow = reactive({
  title: '',
  detail: '',
});
const provinceList = ref([]); // 省份信息
let bounds = []; // 范围,new T.LngLat(bounds[0], bounds[1])记录左上点,new T.LngLat(bounds[2], bounds[3])记录右下点
const markersInfo = ref<AnyObject[]>([]); // 标记点与相关信息
onMounted(() => {
  try {
    initTdtMap(); // 初始化天地图
  } catch (error) {
    console.log(error);
  }
});
onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeFn);
});
function initTdtMap() {
  tdtMap.value = new T.Map(tdtMapRef.value);
  let postStr = {
    searchWord: '中国', // 查询关键字
    searchType: '1', // 查询类型(0:根据code查询,1:根据名称。)。
    needSubInfo: true, // 是否需要下一级信息
    needAll: false, // 是否需要所有子节点
    needPolygon: true, // 是否需要行政区划范围
    needPre: false, // 是否需要上一级所有信息
  };
  administrative.search(postStr, (res) => {
    if (res.getStatus() == 100) {
      let data = res.getData()[0];
      provinceList.value = data.child ?? []; // 记录省份信息
      // console.log(data);
      setMap(data);
    } else {
      res.getMsg();
    }
  });
}
// 设置中心点、级别和可拖动范围
function setMap(data) {
  // 范围、中心点、缩放级别
  bounds = data.bound.split(',');
  tdtMap.value.centerAndZoom(
    new T.LngLat((bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2),
    4
  ); // 第一个参数中心点坐标(我这里根据范围自动计算的),第二个参数缩放级别
  setPoint(); // 设置标记点
  setSVG(); // 设置边缘线背景图SVG
  window.addEventListener('resize', resizeFn); // 自适应大小
}
const resizeFn = () => {
  try {
    tdtMap.value.checkResize();
  } catch (error) {
    console.log(error);
  }
};
// 设置标记点
async function setPoint() {
  tdtMap.value.clearOverLays(); // 清空已有标记
  // 初始化标记点信息弹框
  infoWin = new T.InfoWindow();
  infoWin.setContent(infoRef.value);
  infoWin.addEventListener('close', function () {
    currentWindow.detail = '';
  });
  let res = await GetMapDataApi({unitguid: unitguid});
  if (res) {
    markersInfo.value = res?.obj ?? [];
    markersInfo.value.map((row) => {
      let item: any = provinceList.value.find((el: AnyObject) => el.name?.includes(row.Province)); // 找到对应身份信息
      let point = new T.LngLat(item.lnt, item.lat); // 设置点
      let marker = new T.Marker(point, { icon: markerIcon }); // 创建标注
      tdtMap.value.addOverLay(marker);
      marker.addEventListener('mouseover', function () {
        currentWindow.title = row?.title || '';
        currentWindow.detail = row?.detail || '';
        marker.openInfoWindow(infoWin); // 点击标注打开弹框
      });
    });
  }
}
// 设置边缘线背景图SVG
function setSVG() {
  let imgURL = require('@/assets/img/chinamap.svg');
  var bd = new T.LngLatBounds(new T.LngLat(bounds[0], bounds[1]), new T.LngLat(bounds[2], bounds[3]));
  let img = new T.ImageOverlay(imgURL, bd, {
    opacity: 1,
    alt: '中国',
  });
  tdtMap.value.addOverLay(img);
}
</script>
<style lang="scss" scoped></style>
.divTdtMap {
  margin: 16px;
  padding: 0px;
  width: 100%;
  z-index: 0;
}
:deep(.tdt-infowindow-content-wrapper) {
  padding: 0;
  width: 150px;
  .tdt-infowindow-content {
    margin: 0;
    width: 150px;
  }
}
.infoDiv {
  width: 150px;
  .title {
    padding-left: 10px;
    padding-right: 30px;
    color: #3a76e4;
    background-color: #eaf4ff;
    line-height: 30px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .contentDiv {
    padding: 10px;
  }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值