尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
天地图API开发实战:源码解析、密钥配置与WMTS瓦片加载
简介面向 Vue 前端开发者的一套天地图 API 完整源码示例包基于 Element Plus UI 框架构建地图应用系统演示了从初始化地图、点标记管理、位置搜索、距离测量到卫星/地图切换、全屏显示等核心交互功能的完整编码流程适合需要快速接入天地图能力的前端工程师参考并提供了完整清晰的示例代码。资源包共 2000 个文件其中 JavaScript 文件 1904 个是各功能模块的实现主体Markdown 文档 55 个用于说明接口调用思路与开发笔记JSON 配置 41 个存储地图参数与示例数据压缩包整体约 31.7MB目录按功能模块组织检索与复用都很便捷。已有 99 人浏览学习。除基础地图功能外包内还集成了天气信息展示、用户当前定位、标记保存与删除等实用扩展模块并附完整可运行源码开发者既可对照学习天地图 API 的调用细节也能直接基于现有代码修改二次开发有效降低地图功能落地成本。1. 天地图API开发示例源码一套能立刻跑起来的地图应用基线做开发这些年我拆过不少号称“万能”的地图代码包真正打开就能跑的不多。这套天地图API开发示例算是个例外它以天地图官方JavaScript API(v4.0)为基础把地图初始化、图层加载、矢量与影像底图切换、Marker标注、线面绘制、事件绑定和地理编码这些基础但必不可少的操作全部收进了一个结构紧凑的源码包里。对刚接触天地图的开发者来说它的价值不在手册式讲解而在于给你一条清晰的主线——照着入口文件往下一路读就能弄明白天地图从“申请key”到“地图上墙”的完整链路。做GIS展示、跑项目原型、交毕业设计或者暂时不想把精力花在自建底图上这套代码都值得下载来改。2. 天地图的坐标与授权机制先看懂这几层再动手改代码2.1 天地图API和其他地图API的差别天地图API并不只是一个地图显示库它背后还有地理编码、逆地理编码、关键字检索、路径规划这一整组Web服务接口。相比常见的商业地图开放平台它的优势在于瓦片由官方统一维护更新节奏稳定并且接口习惯按测绘行业规范来设计弱势也很诚实——文档更新偏慢网上社区讨论量小遇到问题往往得自己抓请求看返回。这套源码恰好保留了官方接口原始的调用风格地图对象用T.Map叠加物用T.Marker、T.Polyline事件监听用addEventListener。整体写法偏经典JavaScript语法跟现代Vue、React组件化风格不太一样但这反而更容易让人理解底层渲染逻辑。你在浏览器里看到的一切图层叠加本质上都是对这些基础对象的组合操作。2.2 密钥体系浏览器端key、服务端key与域名白名单天地图的密钥分为两类浏览器端key和服务端key。浏览器端key用于前端页面直接请求瓦片和Web服务受域名白名单约束服务端key用于服务器之间的通信不绑定浏览器环境主要场景是后端代理。我见过不少翻车现场有人把服务端key写到页面里结果浏览器端出于安全策略拒绝加载也有人图省事后端代理时直接拿浏览器端key拼请求服务端上能通换到浏览器一访问就被跨域和Referer校验拦下来。处理方式并不复杂浏览器端key绑定你实际访问页面的域名本地调试时也要把localhost、127.0.0.1加进白名单。服务端key只放在后端工程里例如Java的application.yml、Node的.env不要出现在任何前端源码里。key在URL里以tk参数形式出现建议在源码里统一抽成一个常量后面换域名或者更新key时只改一个地方。在实际项目里我会在源码顶部写一行const TD_TK 你的tk所有瓦片URL和接口请求都引用这个常量。这样既方便替换也避免某一段代码里残留旧key导致整张地图白屏。2.3 投影参数与WMTS的TILEMATRIXSET坐标坑的源头这是天地图开发里最容易让人迷惑的一层。天地图官方JavaScript API初始化时通常写成projection: EPSG:4326也就是经纬度坐标系。但它的WMTS切片服务又分两套切图方案TILEMATRIXSETw对应Web墨卡托TILEMATRIXSETc对应经纬度切图。简单说用官方T.Map时投影属性写EPSG:4326没问题底层渲染会对齐。但如果你绕过官方API直接拼瓦片URL给Leaflet、OpenLayers或者自研渲染引擎就必须注意参数映射TILEMATRIXSETw时TILEMATRIX对应z轴缩放级别TILEROW对应y方向瓦片序号TILECOL对应x方向瓦片序号即z/y/x顺序。TILEMATRIXSETc时同样用z/x/y但瓦片切片原点不同同一坐标在不同层级下对应的行列号会有差异。我一般会写一个辅助函数来拼URL把z、x、y传进去把TILEMATRIX、TILEROW、TILECOL固定好顺序避免每次手写都猜一遍。这个细节关系到后面影像、矢量底图对不对得上先记下第五节我会展开讲具体排查案例。3. 源码落地从入口文件到图层切换3.1 源码包里先看这三个文件拿到这套源码包不用急着全部读完。我的建议是按照“入口 → 配置 → 主逻辑”的顺序看index.html页面骨架引入天地图JavaScript API的script标签就藏在这里tk参数也在这个标签里出现。config.js集中存放key、瓦片URL模板、常用坐标点。真要改配置基本都是改这个文件。main.js地图初始化和交互逻辑所有功能模块的调用入口。先说index.html里那段必不可少的引入代码script srchttps://api.tianditu.gov.cn/api?v4.0tk你的浏览器端tk/script这段代码的作用是加载天地图官方JavaScript API。注意v4.0是版本号目前官方稳定支持到4.xtk必须是浏览器端key不能是服务端key。如果这里填错后面所有地图对象都不会被创建。3.2 地图初始化的最小代码块打开main.js最核心的初始化逻辑通常是这样// 1. 创建地图实例绑定页面中的div容器 var map new T.Map(mapDiv, { projection: EPSG:4326 // 天地图使用经纬度坐标系 }); // 2. 设置地图中心和缩放级别 // 参数分别对应经度、纬度、缩放级别(数字越大显示越细) map.centerAndZoom(new T.LngLat(120.5, 30.1), 10);这段代码里T.Map构造函数的第一个参数是页面里div元素的id。需要确认这个div有明确的宽度和高度否则地图容器高度为0初始化后白茫茫一片看不到任何东西。centerAndZoom接收一个T.LngLat对象这里的(120.5, 30.1)只是一个示例坐标实际项目里可以替换成目标区域经纬度。缩放级别10相当于市级范围12到14适合城区细节18以上一般就到楼栋级别了。初始化之后还要把图层加进去才看得到地图。源码里通常会提前声明几个图层变量// 矢量底图(带中文注记) var vecLayer new T.TileLayer( https://t{0-7}.tianditu.gov.cn/vec_w/wmts?SERVICEWMTSREQUESTGetTileVERSION1.0.0LAYERvecSTYLEdefaultTILEMATRIXSETwFORMATtilesTILEMATRIX{z}TILEROW{y}TILECOL{x}tk TD_TK ); // 影像底图(带中文注记) var imgLayer new T.TileLayer( https://t{0-7}.tianditu.gov.cn/img_w/wmts?SERVICEWMTSREQUESTGetTileVERSION1.0.0LAYERimgSTYLEdefaultTILEMATRIXSETwFORMATtilesTILEMATRIX{z}TILEROW{y}TILECOL{x}tk TD_TK ); // 默认添加矢量图层 map.addLayer(vecLayer);这里需要说明一点t{0-7}是天地图的瓦片子域名通配符官方会将请求自动分配到8个子域名(t0到t7)浏览器并发加载瓦片时速度更快。如果你拿这段URL直接放到其他地图库需要把{0-7}翻译成目标库自己的多域名语法比如{s}前缀配置。3.3 矢量、影像、地形底图切换逻辑源码包里的图层切换功能核心就是addLayer和removeLayer的组合调用。以矢量、影像、地形三种底图为例切换逻辑写成函数大概是这样window.switchLayer function (layerType) { // layerType : vec 矢量 / img 影像 / ter 地形 var layerMap { vec: vecLayer, img: imgLayer, ter: terLayer }; var activeLayer layerMap[layerType]; // 先移除所有已有底图 map.removeLayer(vecLayer); map.removeLayer(imgLayer); map.removeLayer(terLayer); // 再添加目标底图 if (activeLayer) { map.addLayer(activeLayer); } };把图层从地图上移除时如果该图层本来就不在地图上removeLayer并不会报错所以先全部移除再添加是安全的写法。这里有个隐患如果矢量、影像、地形三个图层来自不同的URL模板务必保证每一个模板里的tk都是同一个浏览器端key否则切图时某一张底图会加载不出而其他底图表现正常表面看是异步加载问题实际是key不匹配。4. 常用功能模块标注、绘制、事件与地理编码4.1 添加Marker标注并绑定信息窗标注是地图应用最常用的能力源码里把Marker和InfoWindow的绑定做成了一个通用函数结构上很适合直接套用到项目里。function addMarker(lng, lat, title, content) { var lngLat new T.LngLat(lng, lat); var marker new T.Marker(lngLat); // 给标注点绑定点击事件点击后弹出信息窗 var infoWindow new T.InfoWindow( div stylepadding:8px;font-size:14px; h4 stylemargin:4px 0; title /h4 p stylemargin:4px 0;color:#555; content /p /div, { offset: new T.Point(0, -30) } // 信息窗向上偏移避免遮住标注点 ); marker.addEventListener(click, function () { map.openInfoWindow(infoWindow, lngLat); }); map.addOverLay(marker); return marker; }注意几个细节addOverLay不是addLayer——addLayer用于整块底图addOverLay用于点线面叠加物T.InfoWindow接收HTML字符串在Vue或React环境里可以拼接原生DOM节点转成字符串也可以动态生成HTML再塞进去offset参数控制信息窗相对标注点的偏移量通常是负值向上偏移不然弹窗会把Marker图标盖掉。4.2 用Polyline、Polygon绘制线路与区域绘制轨迹、围栏这类需求源码里写成了通用绘制函数。以折线为例function drawPolyline(points, color) { // points 格式[[lng, lat], [lng, lat], ...] var latLngs points.map(function (item) { return new T.LngLat(item[0], item[1]); }); var polyline new T.Polyline(latLngs, { color: color || #4A90D9, // 线条颜色 weight: 4, // 线条宽度 opacity: 0.8 // 透明度 }); map.addOverLay(polyline); return polyline; }T.Polyline的第一个参数是一个T.LngLat数组第二个参数的weight在官方API里表示线宽如果绘制效果感觉线条很细先别急着调样式确认一下是不是单位与CSS像素不一致的问题。常见做法是将weight设置成4或者6视觉效果比较贴近地图常规线宽。同样绘制区域用T.Polygon构造参数和T.Polyline基本一致只是内部会自动闭合首尾坐标。如果你要做围栏编辑功能源码包里还会用到map.enableEdit()之类的方法但这个功能在不同版本里表现有差异建议先用示例代码验证一次再依赖它。4.3 调用天地图服务接口做地理编码这套源码还封装了一个非常实用的地理编码函数用来把地址文字转换成经纬度坐标。它调用的是天地图Web服务接口不需要借助任何第三方库直接fetch就行。async function geocode(address) { var postStr JSON.stringify({ keyWord: address, // 要查询的地址 level: 12, // 在城市时返回行政区中心坐标 mapType: vec // 返回坐标参考矢量底图 }); var url https://api.tianditu.gov.cn/geocoder?postStr encodeURIComponent(postStr) typegeocodetk TD_TK; var resp await fetch(url); var data await resp.json(); // 返回数据结构data.location 为 { lon: xxx, lat: xxx } return data.location; }这个接口的请求体是一个JSON字符串postStr参数必须先用encodeURIComponent编码再拼到URL上否则地址里带中文、括号、百分号时很容易解析失败。level参数的取值会影响返回坐标精度取12时大概是市级精度取18时会更贴近街道级别但也不是值越大越准因为有些偏地名在低层级就返回了中心点。源码里这个level: 12的设计是为了避免一个地址匹配到多个区域时产生明显偏差。配合前面的addMarker函数可以快速把地理编码结果落到地图上geocode(某市科技园区).then(function (location) { addMarker(location.lon, location.lat, 定位结果, 来自地理编码服务); map.centerAndZoom(new T.LngLat(location.lon, location.lat), 14); });这里要注意data.location返回的字段名是lon和lat有人习惯写lng拿到undefined再去找原因不值当。5. 常见问题与排查图层空白、坐标错位、tk失效的五个现场5.1 地图白屏瓦片请求返回404或401现象是页面框架、缩放按钮都渲染出来了但地图区域一片空白打开浏览器Network面板能看到大量瓦片请求失败。原因有两个方向一是网段本身无法访问天地图服务这是网络环境问题二是tk参数未通过校验。前者只能换网络环境后者检查一下页面里引用的tk是否属于浏览器端key以及这个key的白名单里是否包含当前访问域名。file://协议打开页面时Referer字段为空很多key校验策略直接拒绝所以本地调试尽量起一个本地服务比如python -m http.server 8080再用http://localhost:8080访问。处理方式也直接把当前测试域名填进天地图开放平台控制台的域名白名单等1到5分钟生效。如果填完后仍然白屏再检查地址栏里的URL是不是带端口白名单需要精确到端口时可以填localhost:8080。5.2 影像底图和矢量底图重叠时坐标对不上现象是分别显示时都正常但把影像底图叠加在矢量底图之上或者切换对比时道路、建筑位置整体偏移偏移量随缩放级别变化。原因几乎可以锁定为两套图层使用了不同的TILEMATRIXSET。常见误用是一张瓦片地址写了TILEMATRIXSETc另一张写了TILEMATRIXSETw。同一个坐标点在经纬度切图和Web墨卡托切图里的瓦片行列号不同叠在一起自然错位。解决方法是统一TILEMATRIXSET。我一般统一使用w因为现代前端地图库对Web墨卡托更友好而且天地图的w切片在所有缩放级别下覆盖完整。如果你依赖官方T.Map初始化投影写EPSG:4326并不冲突底层的瓦片坐标系由API自己对齐真正要警惕的是跨库使用时把URL模板直接搬过去。5.3 本地调试时Marker标注和底图对不上现象是标注点落在马路中间、湖泊中央或者偏移一个街区的距离。原因通常有两个层面一是经纬度顺序写反。T.LngLat构造函数是(经度, 纬度)但有人从数据库里拿到的是(纬度, 经度)直接传进去初始化时又恰好没开启严格模式坐标就偏到别处去了。二是基准面差异设备采集的GPS坐标是WGS84天地图官方底图数据基于CGCS2000二者在大部分城市区域误差在几米以内但个别偏远区域可能明显。对于网页应用几米误差在12级以内表现不明显放大到18级就会有点扎眼。解决方式先确认代码里所有new T.LngLat(lng, lat)的参数顺序前端统一写经度在前再用官方一个已知坐标点位做标定比如源码包里的示例坐标看Marker是否对准。如果GPS坐标有固定系统偏差可以在进入页面前做一个坐标系转换处理。5.4 生产环境切换域名后tk突然失效现象是开发环境一切正常部署到测试环境后地图全白控制台报无效key错误。原因在于天地图浏览器端key与域名白名单是强绑定的。开发环境用localhost测试环境换成内网IP或者临时域名key自然失效。处理方式也简单把新域名加入白名单。注意有时新域名备案、端口、协议变化都会影响Referer匹配。经验是保留开发域名的同时把测试、预发布、正式域名都提前加进去并设置一个较长的生效缓冲期。另外如果有后端代理转发瓦片请求代理请求里也必须携带正确的tk建议后端单独保存一份服务端key不沿用前端的浏览器端key。5.5 直接双击index.html能出图但别人访问时出不来现象是自己在本机双击打开没问题局域网内其他设备通过IP访问时白屏。原因在于file://协议下浏览器对Referer的限制比较宽松而换成http://192.168.x.x访问后这个内网IP并不在你绑定key时的白名单内。解决方法是把内网IP加入白名单或者统一走一个内网域名。更省事的做法是开发阶段在天地图控制台同时添加localhost和测试域名的白名单不依赖本地文件协议。以后我拿到任何带地图的代码包第一件事就是检查key白名单和协议头不在浏览器上耗时间。6. 进阶技巧越过官方API直接拼WMTS瓦片地址官方API能把大部分需求包圆但如果你在做前端框架集成或者需要把天地图瓦片接进自定义地图引擎就得自己拼瓦片地址。这个套路也叫“裸瓦片加载”好处是不依赖官方JavaScript API渲染调度完全由自己的引擎控制。先验证一张瓦片是否能直接访问用命令行最省事curl -g \ https://t0.tianditu.gov.cn/vec_w/wmts?SERVICEWMTSREQUESTGetTileVERSION1.0.0LAYERvecSTYLEdefaultTILEMATRIXSETwFORMATtilesTILEMATRIX4TILEROW2TILECOL3tk你的tk \ -o tile_4_2_3.jpg这条命令里的TILEMATRIX4是缩放级别TILEROW2和TILECOL3是该层级下的瓦片行列号。执行后如果得到一个JPEG文件说明地址拼接和key都正常。如果返回的是XML错误文本优先检查TILEMATRIXSET参数是否写成了c或者tk是否有效。验证通过后就可以在自己封装的地图组件里用循环拉瓦片。以Python脚本为例批量下载某一区域某层级的瓦片import requests TK 你的tk url_template ( https://t{0}.tianditu.gov.cn/vec_w/wmts ?SERVICEWMTSREQUESTGetTileVERSION1.0.0 LAYERvecSTYLEdefaultTILEMATRIXSETw FORMATtilesTILEMATRIX{z}TILEROW{y}TILECOL{x}tk TK ) # 以层级10、中心瓦片坐标(512, 340)周围3x3范围为例 for row in range(339, 342): for col in range(511, 514): url url_template.format(xcol, yrow, z10) resp requests.get(url, timeout10) with open(ftile_{row}_{col}.jpg, wb) as f: f.write(resp.content)注意这里的row对应URL里的TILEROWcol对应TILECOL。写脚本时最容易弄反一旦反了下载下来的图片拼接时会顺序错乱。另一个技巧是把t0换成t1到t7做并发下载多线程拉瓦片时速度提升明显但不要突破浏览器同源并发限制太多否则服务端会主动限流。这个方法还能用来做离线缓存。我接过一个内网项目前端无法直接访问外网天地图就在服务端写了一个瓦片缓存代理第一次请求从官方拉取并存到本地磁盘后续请求直接读磁盘配合Nginx静态资源服务效果等同于内网部署了一套底图服务。实现代理时要在服务端配置服务端key出网请求带上它返回给前端时走代理域名不暴露任何外部地址。从那以后我每次拿到这类地图源码都会先拼一个瓦片URL用命令行拉下来看返回内容确认图层参数、key、网络链路全通之后再进代码改业务。这一步能省掉后面大量的地图调试时间。希望帮到你。本文还有配套的精品资源点击获取
RELATED

相关推荐

AI自动排优先级:应付账款智能排序方案与资金管理优化实践

AI自动排优先级:应付账款智能排序方案与资金管理优化实践

付款顺序这件事,看上去是个"把到期日排个先后"的小问题,真正做下来才发现里面全是水。我接触过一个真实的案例:某制造业公司账上每月要付出去的资金在一个亿上下,应付账款挂了几百笔,供应商从几十家到上百家…

📅 2026/10/19 0:54:59
黑熊检测专用数据集:小目标、强遮挡、光照突变下的野外落地方案

黑熊检测专用数据集:小目标、强遮挡、光照突变下的野外落地方案

简介:本资源为面向目标检测初学者与算法实践者的黑熊(棕熊)专用检测数据集,适用于YOLO系列等主流检测模型的训练、验证与部署调试。数据集基于COCO2017精筛构建,共含1009张高质量标注图像(jpg)&…

📅 2026/10/19 0:54:59
保本跟单系统:把损失边界锁进交易规则的工程实践

保本跟单系统:把损失边界锁进交易规则的工程实践

保本跟单:让投资的结果变得可控很多人第一次听到“保本跟单”这四个字,第一反应和我当初一样:警惕。做交易这些年,见过太多平台把“稳赚”“保本”挂在嘴边,最后跑路的跑路、爆仓的爆仓,说多了都是泪。但后…

📅 2026/10/19 0:54:59
MORE NEWS

更多资讯

📰

EMC整改无效的根源:屏蔽与接地必须做到电连续和低阻抗

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

如何把Qwen-Image-Layered-6bit接入你的工作流:RGBA图层在PS、Figma中的实战用法

【免费下载链接】Qwen-Image-Layered-6bit 项目地址: https://ai.gitcode.com/hf_mirrors/zimengxiong/Qwen-Image-Layered-6bit 点击查看 免费下载 Qwen-Image-Layered-6bit 是一款专为 Apple Silicon(M1/M2/M3/M4 芯片)优化的 6-bit 量化图…

📰

树莓派GPIO实战:DS18B20温控风扇PWM调速与回差控制

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

三步跑通属于你自己的免费 LLM API:FreeLLMAPI 本地部署与接入完整教程

三步跑通属于你自己的免费 LLM API:FreeLLMAPI 本地部署与接入完整教程 【免费下载链接】freellmapi 7.4 billion tokens per month. 34 free LLM providers. 635 free model endpoints. All behind one /v1 endpoint, plus any custom OpenAI-compatible endpoint.…

📰

RocooFix静态修复完全指南:补丁如何注入ClassLoader实现代码替换?6步拆解完整流程

【免费下载链接】RocooFix another hotfix framework 项目地址: https://gitcode.com/gh_mirrors/ro/RocooFix 点击查看 免费下载 RocooFix 是一款轻量级 Android 热修复框架:线上出现 Bug 时,只需推送一个小型的 patch.jar,App …

📰

TFLM在Arm MCU上的端侧AI部署实战:从模型转换到性能调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬