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

发布时间:2026/6/23 3:22:22
vue3使用天地图记录,百度地图改使用天地图 目录天地图基础旧项目改用天地图历史坐标点会有偏移的原因转换方法百度地图bd09II坐标转换天地图CGCS2000坐标json转化bigemap网站获取可以获取街道数据展示页完整示例代码中国范围后端接口提供每个省相关信息CDN引用回调中还是会出现tk天地图基础官方网址: 天地图国家地理信息公共服务平台1.登录2.创建新应用3. public/index.html注代码内{}表示注释需连同大括号一起替换html lang head script srchttp://api.tianditu.gov.cn/api?v4.0tk{天地图-应用管理-Key名称} typetext/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高德地图下载json文件调用下面的方法将控制台打印的结果拷贝保存到项目中import { datavJson } from ./datavJson; /** * 新项目通过这个方法将datav获取的边框线转为天地图坐标线只需要运行一次会将转化后的结果打印在控制台 * datavJsondatav拷贝下来的数据 * 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网站获取可以获取街道数据参考文档1https://blog.csdn.net/weixin_44861708/article/details/114223258参考文档2https://www.yuucn.com/a/1565092.html所需数据来源kml文件http://www.bigemap.com/reader/download/转geojsonhttp://www.bigemap.com/reader/download/展示页完整示例代码中国范围后端接口提供每个省相关信息template div reftdtMapRef classdivTdtMap/div div refinfoRef classinfoDiv v-showcurrentWindow.title div classtitle{{ currentWindow.title }}/div div classcontentDiv弹框详细信息{{ currentWindow.detail }}/div /div /templatescript langts 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 refAnyObject[]([]); // 标记点与相关信息 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 langscss 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引用回调中还是会出现tkimport { 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?v4.0tk${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, }; }