尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

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

vue3使用天地图记录,百度地图改使用天地图
📅 发布时间:2026/6/23 3:32:40

目录

天地图基础

旧项目改用天地图

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

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

json转化

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

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

CDN引用(回调中还是会出现tk)


天地图基础

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

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; } }

CDN引用(回调中还是会出现tk)

import { ref } from 'vue'; export function useCDN() { const isLoading = ref(false); const error = ref(''); const loadScript = async (src) => { isLoading.value = true; error.value = ''; try { // 检查是否已存在 if (document.querySelector(`script[src="${src}"]`)) { isLoading.value = false; return Promise.resolve(); } return new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = src; script.async = true; script.onload = () => { isLoading.value = false; resolve(true); }; script.onerror = () => { isLoading.value = false; error.value = `Failed to load script: ${src}`; reject(new Error(error.value)); }; document.head.appendChild(script); }); } catch (err: any) { isLoading.value = false; error.value = err.message; throw err; } }; const loadScripts = async (sources) => { for (const src of sources) { await loadScript(src); } }; async function fetchFn() { const apiKey = process.env.VUE_APP_TIANDITU_API_KEY; const response = await fetch(`https://api.tianditu.gov.cn/api?v=4.0&tk=${apiKey}`, { headers: { Accept: 'application/javascript, */*', }, }); const data = await response.text(); const script = document.createElement('script'); script.textContent = data; script.type = 'text/javascript'; document.head.appendChild(script); } return { isLoading, error, loadScript, loadScripts, fetchFn, }; }

相关新闻

  • 基于思维树预测LLM代码生成准确性的工程实践
  • 2026行业内质量好的线切割机床生产商怎么选 - 品牌排行榜
  • Vibe Coding:一种面向快速验证与个人提效的开发者节奏感

最新新闻

  • 国内稳定调用Gemini的轻量兼容层实践
  • Python print():零基础AI提示词工程的第一课
  • 国际化技术软件多语言支持与本地化测试的流程管理
  • 20+开箱即用的前端驾驶舱模板,React/Vanilla JS实现,含完整源码和本地运行示例
  • Android自动化测试终极指南:从JUnit、Espresso到UI Automator实战
  • 百度网盘秒传链接网页工具:终极免费指南,3分钟掌握高效文件传输技巧

日新闻

  • Arduino-ESP32项目深度解析:解锁隐藏芯片支持与架构演进
  • 2026年 系统窗厂家/品牌推荐榜单:隔音系统窗+高端系统门窗的核心优势与选购指南 - 品牌发掘
  • NVBench:首个双语非言语发声语音合成评测基准详解与实践

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号