ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

用天地图API实现导航功能:从Key申请到路线绘制的完整实践

用天地图API实现导航功能:从Key申请到路线绘制的完整实践 前一阵朋友问了个很典型的问题项目要求地图服务必须走官方渠道能不能用天地图API做导航他的需求其实很朴素——输入起终点、选中路线、展示走向最好还能带上分步指引。我拿天地图开放平台实际跑了一遍把JavaScript API和服务端HTTP接口都调通了。这篇就把“使用天地图API实现导航功能”这件事的完整路径写出来包括能做什么、不能做什么、怎么申请Key、代码怎么写、哪些坑必须避。如果你正在选型国产地图服务或者被要求“只用天地图”这篇文章应该能帮你省下不少摸索时间。先说个概念预期如果你以为用天地图API就能像手机地图那样实时播报、车道级引导那建议先把预期降到“路线规划”这个层面——后者才是天地图API真正能稳定提供的能力。把这个边界搞清楚后面开发才不会走偏。1. 先搞清楚天地图的“导航”到底是种什么能力1.1 天地图API能提供什么天地图开放平台的能力可以分成两大块前端JavaScript API和服务端HTTP接口。这两块的定位完全不同但经常被混为一谈。前端JavaScript API主要负责“地图展示交互”核心能力包括底图加载矢量图、影像图、地形图还能叠加注记图层覆盖物Marker点标记、Polyline折线、Polygon多边形、InfoWindow信息窗等交互操作缩放、拖拽、点击事件、鼠标移动事件搜索检索地名搜索、周边检索、逆地理编码路径规划驾车路线、步行路线、公交路线行政区划加载行政边界、区域划分服务端HTTP接口则更偏“数据后端”地理编码把文字地址转成经纬度坐标逆地理编码把经纬度坐标转成文字地址路径规划驾车、步行、公交三条计算接口行政区划查询等其他数据服务用一张表格快速对照能力JavaScript APIHTTP接口地图显示核心能力直接渲染在页面不支持路径规划支持计算完直接绘制支持返回JSON数据地理编码支持支持适用场景Web网页、可视化大屏小程序、App、服务端计算我在实际项目中比较常用的组合是网页端用JavaScript API做交互和展示服务端用HTTP接口做批量计算和数据缓存。两者搭配起来基本能覆盖大多数“导航类”业务场景。1.2 “导航”和“路径规划”不是一回事这是我特别想强调的一个点。天地图API提供的是路径规划Route Planning不是完整的实时导航Navigation。两者差在哪路径规划的意思是你给一个起点、一个终点它帮你算出一条可以走的路线返回这条路的几何形状坐标点串、总距离、预计耗时以及分步的文字指引。它不关心你现在走到哪了也不会在你走错路之后重新规划。实时导航则是另一套东西需要持续获取GPS定位、实时修正位置、检测偏航并自动重算路线、提供语音播报、甚至加上车道级引导。这些能力根本不是单个API接口能搞定的通常需要集成完整的导航SDK或者自研一套导航引擎。打个比方路径规划像是给你一张提前画好路线的手绘地图导航则是坐在副驾一路提醒你的老司机。天地图API能干的是前者而且是稳定输出。所以“使用天地图API实现导航功能”落到产品层面实际交付的东西通常是用户输入或选择起终点调用天地图路径规划接口地图上画出推荐路线展示总距离、预计耗时列出一步步的文字转向指引这套东西已经非常接近日常认知里的“导航”了只是少了实时定位和语音播报这两个模块。如果你的需求正好在这几步之内天地图完全够用。1.3 选天地图的真实理由市面上地图服务并不少为什么要用天地图我接触过的项目里理由通常集中在这么几个合规要求政企项目、涉密单位往往对地图服务商有严格的准入要求必须用国家官方地理信息平台的数据数据权威天地图的数据来自官方测绘成果权威性有保障在产权和审核层面省了很多麻烦免费配额开发者申请Key之后有免费调用额度个人项目和中低流量产品成本压力小国产自主底图瓦片服务器全部在国内数据不依赖海外服务业务上更稳坐标友好使用CGCS2000国家大地坐标系和GPS采集的WGS84坐标差异极小便于对接GNSS数据当然它也有短板比如API文档更新节奏一般、部分JS API类名老版本和新版本不一致、渲染性能比商业地图引擎略保守。这些在后面踩坑部分会详细说。2. 开发前绕不开的三件事Key、白名单和坐标系2.1 申请Key的完整流程与注意事项天地图测试路上的第一道坎不是代码而是Key申请。流程本身不复杂但类型选错会卡你好久。操作步骤大致如下打开天地图开放平台官网注册账号并登录进入控制台通常叫“开发者中心”或“应用管理”创建一个新应用填写应用名称和使用场景说明选择应用类型浏览器端、服务端、Android、iOS等按类型填写域名白名单或IP等信息提交后得到一个tk字符串这就是你的API Key这里最重要的一个注意点浏览器端Key和服务端Key不能混用。JavaScript API引入脚本时使用的tk必须是浏览器端类型的KeyHTTP接口请求时携带的tk必须是服务端类型的Key。我见过太多人拿着浏览器端Key去调HTTP接口返回结果一直是权限错误排查半天发现是Key类型选错了。另外Key相当于你的身份凭证会明文出现在前端代码里所以一定记得配置白名单限制使用来源。如果被他人盗用刷接口轻则配额被耗尽重则影响线上业务。2.2 域名白名单浏览器端API的安全边界创建浏览器端应用时你会被要求填写授权域名。这个域名白名单机制是天地图保护Key不被盗用的核心手段一定要理解到位。白名单的逻辑是只有列表里出现的域名加载天地图JavaScript API时才有效。页面访问域名不在白名单里脚本可能加载成功但初始化地图时直接报错或者请求接口时返回INVALID_TOKEN。开发调试阶段建议写上localhost 127.0.0.1这样本地起HTTP服务调试没问题。但上线前务必把正式域名加进白名单并测试一遍。这里有个坑有些平台修改白名单后不是立刻生效可能需要重新复制Key或者等一小段时间。我通常的做法是上线前提前半天把域名配好留出生效缓冲期。如果你是微信小程序或者原生App用的是WebGL或原生SDK那白名单机制不太一样更多是绑定包名或者AppID申请的时候看清楚类型说明。2.3 坐标系CGCS2000和其他坐标系的偏差天地图使用CGCS2000国家大地坐标系这是一个经常被人忽略但影响巨大的细节。业内几个常见坐标系的对比坐标系主要使用方与CGCS2000的实际偏差CGCS2000天地图基准一致WGS84GPS原始坐标、国际地图服务厘米级到分米级工程上基本可忽略GCJ-02国内多数商业地图明显偏移城市区域可能有几百米这意味着什么如果你手里有一批从高德、腾讯或者百度地图保存下来的坐标点直接搬到天地图上显示位置会偏出去几百米。这不是天地图的问题是坐标系根本不一样。我踩过这个坑项目早期有一些历史POI数据存在高德的库前端展示切换到天地图之后所有点位全部偏移排查了半天才想起坐标系问题。后面统一做法是数据入库前先做坐标转换所有经纬度统一存成CGCS2000/WGS84体系展示层不再处理第二次转换。至于GCJ-02怎么转成CGCS2000正规做法是调用合法的坐标转换服务或者使用天地图自己的逆地理编码接口做校准映射。不要自己封装一个“加偏移量”的土办法不同地区偏移量不是固定的硬编码最后一定会出事。3. 最快跑通的场景浏览器里做驾车路线3.1 页面初始化与地图加载先给一个最基础的HTML页面把天地图JavaScript API引进来初始化一张地图。!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title天地图驾车路线示例/title style html, body, #map { width: 100%; height: 100%; margin: 0; padding: 0; } #panel { position: absolute; right: 0; top: 0; width: 320px; height: 100%; overflow-y: auto; background: rgba(255, 255, 255, 0.92); padding: 12px; box-sizing: border-box; font-size: 14px; border-left: 1px solid #ddd; } /style script srchttps://api.tianditu.gov.cn/api?v4.0tkYOUR_BROWSER_KEY/script /head body div idmap/div div idpanel/div script var map new T.Map(map); map.centerAndZoom(new T.LngLat(116.40969, 39.89945), 12); map.addControl(new T.Control.Zoom()); /script /body /html这里有几个关键点。new T.Map(map)是在指定id的DIV里创建地图实例DIV必须设置宽高否则地图容器高度为0页面会白成一片。T.LngLat(经度, 纬度)是天地图的经纬度对象注意构造函数顺序是经度在前、纬度在后和第二维坐标习惯相反。map.centerAndZoom(lngLat, zoom)用于设置地图中心点和缩放级别缩放级别一般3到18城市级12到14比较合适。加载脚本的URL里必须有tk你的浏览器端Key而且v4.0指定的是API版本。天地图大版本升级时类名可能会有调整引用时先确认开放平台当前推荐版本号。如果页面打开后地图是灰色空白优先检查Network请求里JS有没有加载成功其次检查控制台有没有坐标系、Key相关的报错。3.2 调用T.DrivingRoute搜路线地图能正常显示之后就可以接入驾车路线规划了。天地图JavaScript API里驾车路线的核心类是T.DrivingRoute。示例代码var start new T.LngLat(116.40969, 39.89945); var end new T.LngLat(116.46908, 39.91488); var driving new T.DrivingRoute(map, { routeType: fastest, onSearchComplete: function(result) { // 路线计算完成后的回调 console.log(result); }, onError: function(err) { console.error(路线规划失败, err); } }); driving.search(start, end);routeType是路线偏好常用的几个值fastest最快路线优先速度shortest最短路线优先距离leisure小路、景观路优先avoidHighway避开高速具体取值在不同版本文档里略有不同不过这几个是相对稳定的。选型逻辑很简单给网约车司机类用户用fastest给骑行或旅游场景用leisure货车类路线还要额外考虑限行政策天地图这部分能力有限需要业务侧自研。onSearchComplete是核心回调接口计算完成后会带着结果对象触发。一定要先在这里打日志看结构因为不同版本里result对象的字段名可能有出入。我每次升级版本都会先跑一遍这行代码。3.3 把返回结果画成路线并展示提示onSearchComplete: function(result) { // 有些版本用result.getStatus()判断状态0表示成功 if (result.getStatus result.getStatus() ! 0) { return; } // 取第一个路线方案 var plan result.getPlan(0); var route plan.getRoute(0); // 从route上取坐标点串 var path []; if (route.getPath) { path route.getPath(); } // 创建折线覆盖物并添加到地图 var polyline new T.Polyline(path, { color: #00A0FF, weight: 6, opacity: 0.8 }); map.addOverLay(polyline); // 标记起点和终点 map.addOverLay(new T.Marker(start)); map.addOverLay(new T.Marker(end)); // 展示文字指引 var panel document.getElementById(panel); panel.innerHTML ; var timeText plan.getTime ? plan.getTime() 秒 : -; var distText plan.getDistance ? plan.getDistance() 米 : -; panel.innerHTML p预计耗时 timeText 距离 distText /p; if (route.getNumSteps) { var totalSteps route.getNumSteps(); for (var i 0; i totalSteps; i) { var step route.getStep(i); if (step.getInstruction) { panel.innerHTML p step.getInstruction() /p; } } } }这段代码的流程是拿到方案 - 取第一条路线 - 取坐标点串 - 画线 - 加起终点Marker - 渲染文字步骤。注意T.Polyline构造函数接收的是一个包含T.LngLat对象的数组。如果接口返回的是字符串形式的坐标对比如116.40,39.90;116.41,39.91你需要自己解析成对象数组再传入。后面HTTP接口章节会给出一个完整的解析函数。addOverLay是天地图添加覆盖物的统一方法Marker、Polyline、Polygon都是这么加进去的大小写注意别写错。另外一个隐藏细节如果同一个页面上用户多次搜索路线上一次画的折线不会自动清除。后面搜新的路线时页面上会叠着好几层旧线非常混乱。我建议自己维护一个overlays数组每次搜索前先把旧的覆盖物删掉。天地图里逐个删除覆盖物的方法是map.removeOverLay(overlay)手动遍历清理即可。4. 不走浏览器服务端HTTP接口的路线计算4.1 请求参数与URL构成JavaScript API适合网页交互但如果你的产品是微信小程序、原生App或者后端需要批量计算路线就要用到服务端HTTP接口了。天地图路径规划的几个HTTP接口驾车https://api.tianditu.gov.cn/drive步行https://api.tianditu.gov.cn/walk公交https://api.tianditu.gov.cn/bus以驾车为例一次完整请求的URL长这样https://api.tianditu.gov.cn/drive?postStr{orig:116.37525,39.91578,dest:116.43046,39.91772,style:0}typesearchtkYOUR_SERVICE_KEY请求方式是GET参数主要有三个参数说明postStrJSON字符串包含起终点等信息type固定值searchtk服务端应用KeypostStr里的核心字段orig起点坐标格式是经度,纬度dest终点坐标格式同上style路线偏好不同数值对应不同策略具体含义官方文档有说明最坑的细节是orig和dest的顺序。我一开始以为是纬度,经度结果接口返回结果一路都是歪的后来对照文档才确认是经度,纬度这个顺序跟T.LngLat构造函数是一致的。另一个容易忽略的是URL编码。postStr里包含花括号、引号、中文冒号等特殊字符直接拼接在URL里可能被服务端解析错。正确做法是用encodeURIComponent对整个postStr做一次URL编码var postStr JSON.stringify({ orig: 116.37525,39.91578, dest: 116.43046,39.91772, style: 0 }); var url https://api.tianditu.gov.cn/drive?postStr encodeURIComponent(postStr) typesearchtk serviceKey;在服务端用Python、Java等语言请求时同理一定要对参数做URL编码否则线上环境偶尔会出现“接口返回但数据不对”的诡异问题。4.2 返回数据结构与解析逻辑服务端接口返回的是标准JSON结构大致这样不同版本字段略有差异以官方文档为准{ status: 0, msg: ok, result: { orig: 116.37525,39.91578, dest: 116.43046,39.91772, routes: [ { distance: 24057, time: 2500, steps: [ { stepInstruction: 从起点出发, polyline: 116.37525,39.91578;116.37921,39.91602;... } ] } ] } }核心字段含义status状态码0通常表示成功非0值对应不同错误类型result.routes路线方案数组驾车一般返回一个方案distance路线总距离单位米time预计耗时单位秒steps分步指引每步包含文字说明和坐标串注意steps里的polyline是一个长字符串用分号分隔坐标对坐标对内部用逗号分隔经度和纬度。解析的时候按分号切分、再按逗号切分、转成数值即可。function parsePolyline(raw) { var points raw.split(;); return points.map(function(item) { var parts item.split(,); return { lng: parseFloat(parts[0]), lat: parseFloat(parts[1]) }; }); }拿到解析后的坐标数组如果要在地图上画线再转换一次var path parsedPoints.map(function(p) { return new T.LngLat(p.lng, p.lat); }); var polyline new T.Polyline(path, { color: #00A0FF, weight: 6, opacity: 0.8 }); map.addOverLay(polyline);这套逻辑不管是JavaScript API直接返回的route.getPath()还是HTTP接口返回的坐标串最终都能统一成“LngLat对象数组”提交给Polyline所以封装一个通用的绘制函数非常值。4.3 服务端调用的几个实际建议服务端调用HTTP接口和浏览器端不太一样有几个工程上的建议服务端Key绝对不要下发到前端。前端页面里一旦出现服务端Key等同于把接口密钥公开了盗刷风险和费用风险都是自己的。小程序里建议把请求放在云函数或自建服务端转发。对热门路线做缓存。比如上下班通勤、常用商业网点之间的路线结果变化不频繁完全可以在Redis里缓存一份设置合理的过期时间比如24小时能省掉大量接口调用。设置超时和重试。路径规划接口在高峰期可能出现慢响应服务端调用建议设置3到5秒超时失败时做一次指数退避重试不要把错误直接抛给前端。关注配额限制。免费Key有日调用量和并发限制高并发场景需要申请更高配额或者做请求排队。上线前最好用压测工具打一下接口确认瓶颈在哪里。我的一个项目里就是用HTTP接口做了服务端聚合前端提交起终点后端统一调用天地图计算把结果转成统一的内部数据结构缓存起来再提供给小程序端渲染。这样前端不接触Key也方便未来切换别的地图服务商。5. 步行和公交另外两种路径规划模式5.1 步行路径规划的调用差异驾车的路子跑通之后步行和公交基本就是改参数的问题但细节上还是有差异。JavaScript API里步行路线的核心类是T.WalkingRoutevar walking new T.WalkingRoute(map, { onSearchComplete: function(result) { var plan result.getPlan(0); var route plan.getRoute(0); var path route.getPath(); var polyline new T.Polyline(path, { color: #00CC66, weight: 6, opacity: 0.8 }); map.addOverLay(polyline); } }); walking.search(start, end);服务端接口对应的是/walkpostStr参数格式和驾车几乎一样。步行和驾车在数据上最大的区别是路径选择逻辑。步行路线可以穿越天桥、地下通道、公园内部步道这些路汽车走不了而驾车路线会规避步行街、单行道、禁行区域。所以两条路线接口返回的geometry差异很大不能用驾车接口的数据去凑合给步行用户看。我加一句实在话步行路径规划能否好用很大程度上取决于当地路网数据的精细程度。一线城市步道数据齐全体验和主流地图接近三四线城市或者县城步行路线偶尔会出现“穿过空地”“绕远路”的情况。这不是天地图一家的毛病行业内所有地图服务都有这个特性只是数据覆盖范围不同。5.2 公交路径规划的特殊参数公交路线是最“重”的一种路径规划因为公交数据是以城市为单位的跨城换乘计算复杂度高接口参数自然也多。JavaScript API里T.BusRoute的调用一般需要传入城市信息。示意的写法var bus new T.BusRoute(map, { onSearchComplete: function(result) { var num result.getNumPlans(); // 公交通常有多个换乘方案 for (var i 0; i num; i) { var plan result.getPlan(i); // 一个换乘方案可能包含多段路步行到站、公交、地铁、再步行 var routes plan.getNumRoutes ? plan.getNumRoutes() : 0; } } }); bus.search(start, end, 北京);注意第三个参数传的是城市名。服务端/bus接口的postStr也要带上城市信息具体字段以当前文档为准。公交返回的方案通常是多个不像驾车默认一个。每个方案由多段子路线组成比如“步行500米到XX站 - 坐地铁10号线5站 - 换乘公交 - 步行到达”。前端渲染时不能简单画一条折线而是要把每段子路线按顺序拼接同时在不同交通方式的切换点用Marker标记才符合用户对换乘方案的认知。5.3 真实产品里怎么取舍这三种模式三种路径规划不是无脑三选一而是看你的业务场景场景推荐模式理由到店导航、门店指引驾车 步行用户要么开车要么走路公交占比低出行规划、路线推荐驾车 步行 公交覆盖更广的出行方式物流配送、货车调度驾车自定义需要额外处理限行等规则景区导览、园区导航步行路网简单步行更精准另外公交数据覆盖范围确实有限。如果你面向的是全国用户公交路径规划字段里要处理“该城市不支持公交查询”的降级方案避免用户选公交直接看到空白页面。实际项目里我一般把驾车和步行做成默认启用的Tab公交作为可选Tab当接口返回不支持时自动隐藏。这样产品逻辑简单用户也不容易困惑。6. 实测中踩过的坑从报错到渲染一路排查6.1 KEY错误、跨域与白名单纠结先说一个最普遍的报错场景。我把浏览器端Key填到了服务端HTTP接口里返回结果一直是{ status: 404, msg: Invalid token }当时第一反应是Key写错了重新复制了好几次还是一样。后来翻到创建应用时写的类型说明才反应过来接口调用要用服务端Key不能用浏览器端Key。把Key换成服务端类型后问题立刻消失。这道坎的经验总结浏览器端Key用在script标签的src和JS API内部请求服务端Key用在HTTP接口的tk参数移动端有独立的SDK Key类型同类问题还有跨域和域名白名单。具体表现是页面脚本加载正常但初始化地图时报权限错误API调用在网络请求阶段返回403页面标题都在地图容器里只有灰色和塘沽Logo排查链路非常固定F12打开控制台看Network里请求天地图接口的返回状态确认当前访问域名在应用白名单里确认使用Key的类型和当前场景匹配换一个新建的Key立刻测试排除旧Key被平台侧吊销的情况如果是本地调试确认访问地址是localhost或127.0.0.1而不是局域网IP我见过一个频率很高的误操作本地联调时用的是localhost但上线后页面挂了一查发现白名单里只配了localhost正式域名忘了加。上线检查清单里必须有“Key白名单确认”这一项。6.2 坐标偏移来自不同地图服务的数据打架这是我在做多数据源融合时踩的深坑值得重点讲。项目早期积累了一整套POI数据来源包括高德地图和一些人工采集的GPS设备。前端地图切换成天地图后数据点位全线偏移有的点甚至偏出一两个街区。排查过程很典型先怀疑是Marker添加逻辑写错了检查半天代码没问题再怀疑是接口返回的数据错了拿同一批坐标点在控制台对比发现别的地图上位置是对的最后才反应过来是坐标系不匹配高德用的GCJ-02坐标经过了一次加密偏移GPS采集的原始坐标是WGS84而天地图用的是CGCS2000。三个坐标系硬碰在一起显示效果自然乱七八糟。这类问题没有一个“加个常数就能修正”的万能解因为偏移量随着经纬度不同而变化是局部非线性的。正确思路是建立一条“数据标准化”的流水线数据入库前统一坐标体系把所有来源坐标都转成CGCS2000/WGS84前端展示层不再做任何坐标转换外部系统如果需要GCJ-02坐标在输出层再做一次转换具体转换工具选择上建议优先用天地图自己的地理编码/逆地理编码服务尽量少依赖第三方转换库数据流程更可控。另外提醒一点不要把不同坐标系的坐标直接拼在同一个Polyline里。比如一条路线前半段来自高德API、后半段来自天地图API就算肉眼看着像接得上真实渲染时也容易出现折线中间断裂或角点抖动。统一坐标系之后再做拼接问题会自动消失。6.3 路线绘制的性能与观感优化路线画完只是第一步跑得流畅、好看是另一码事。性能方面首先要避免一个错误习惯把路线上的每个点都单独做成Marker。我曾经在一个路径展示页里干了这种事一次行程上千个坐标点循环addOverLay添加了上千个Marker页面直接卡成PPT。后来改成一次性绘制Polyline流畅度立刻恢复。正确的做法路线几何统一用T.Polyline画一条线只占一个覆盖物起终点用两个Marker做视觉锚点即可中途不需要太多额外覆盖物如果要在路线上显示进度或车标用车标Marker沿着坐标点串做动画但每隔一段时间只更新一次车标位置不要高频操作DOM观感方面几个屡试不爽的小技巧折线颜色用高饱和度的主色调和地图底图形成对比比如蓝底图配橙色线、灰底图配蓝色线权重weight设到6左右比较醒目透明度0.7到0.9之间太透明会被底图道路颜色吃掉起点Marker和终点Marker样式要区分建议起点用绿色圆形、终点用红色方块图标设计要和整体产品风格统一添加InfoWindow展示路线总距离和预计耗时内容精简到一行还有路线重新搜索时覆盖物的清理。天地图没有自带“清除上一次路线”的一键方法或者方法名在各个版本里不一样稳妥做法是自己维护数组var overlayList []; function clearRouteOverlays() { for (var i 0; i overlayList.length; i) { map.removeOverLay(overlayList[i]); } overlayList []; } // 添加路线后 var polyline new T.Polyline(path, {...}); map.addOverLay(polyline); overlayList.push(polyline); overlayList.push(startMarker); overlayList.push(endMarker);每次搜索前先调用clearRouteOverlays()能有效避免路线叠加引起的视觉混乱。这个方法比直接使用map.clearOverLays()更安全因为后者会把页面上的POI标记、行政区边界等所有覆盖物一并清掉。7. 往“导航”再靠近一步的几个玩法7.1 多途经点路线天地图驾车路线支持设置途经点这是做“去加油再回家”“去公司顺路接人”这类业务的基础能力。var start new T.LngLat(116.37525, 39.91578); var end new T.LngLat(116.43046, 39.91772); var waypoint new T.LngLat(116.40528, 39.90403); var driving new T.DrivingRoute(map, { routeType: fastest, onSearchComplete: function(result) { // 结果会包含经过途经点的完整路线 } }); driving.search(start, end, [waypoint]);传入的第三个参数是途经点数组顺序会影响路线计算。如果你的场景是让用户自己添加多个经停点记得在前端做一次排序用户期望的是“起点 - 点1 - 点2 - 终点”的顺序而不是经纬度上的自然序。服务端/drive接口同样支持途经点postStr里加对应字段即可。用HTTP接口还有一个好处可以把“带途经点的常规路线”缓存起来比如“公司到客户A再到客户B”这种固定线路每次直接复用结果不重复消耗配额。7.2 配合地名搜索和逆地理编码如果用户在页面上只能输入经纬度那这个功能离“能用”还很远。要真正贴近导航体验必须配合天地图的地理编码和逆地理编码能力。地理编码的HTTP接口https://api.tianditu.gov.cn/geocoder?postStr{keyWord:北京西站}typegeocodetkYOUR_SERVICE_KEY返回结果里包含匹配到的坐标点。拿到坐标之后再交给路径规划接口去计算路线整个链路就是完整的“输入地址 - 得到路线”。逆地理编码对应另一个方向在地图上点一下拿到这个位置的文字描述。这在用户“选点”场景里非常有用比如在地图上点击设置起点右侧自动显示“北京市海淀区XX路XX号”体验瞬间专业起来。产品交互上可以这样做起终点输入框支持文字搜索匹配到POI后显示候选列表用户点击地图任意位置逆地理编码自动填充地址描述路线展示后在侧边栏显示“起点XX”和“终点XX”而不是干巴巴的经纬度这套组合拳下来用户感觉你接入的是一个完整的路径检索能力而不是一个孤立的接口。7.3 把路线结果封装成你自己的导航面板最后分享一个我比较看重的架构习惯不管底层用的是JavaScript API还是HTTP接口都把路线结果封装成一套内部的数据模型而不是直接操作天地图对象。一个简单的模型长这样var routeModel { distance: 0, duration: 0, polyline: [], steps: [], origin: null, destination: null };从JavaScript API的回调里能拿到这套字段从HTTP接口的JSON里也能解析出这套字段。唯一不同的是数据来源但最终渲染逻辑完全共用。好处很明显换地图服务商时只需要重写一个“适配器”把对方API的返回字段映射到routeModel新增地图渲染SDK时已有的导航面板、距离展示、步骤列表全部复用做单元测试时不需要依赖真实地图环境直接mock一套routeModel数据即可我曾经在一个项目里用这种方式把底图从商业地图切到天地图前端UI几乎没动只替换了数据源层和部分绘制代码。这种解耦思路在长期维护的项目里价值极大。至于要不要把这个面板做成类似“语音导航”的形态我的建议是看成本。实时定位需要接入浏览器Geolocation API或者App原生GPS能力偏航重算需要自己监听位置变化并重新调用路线规划语音播报需要对接TTS服务。每一层都有工作量但每一层都是可插拔的。先把基础的路线查询和展示做好再按业务优先级逐步叠加稳扎稳打。最后提一句实在经验天地图API的文档风格偏工具书示例代码不算多所以在动手写第一个页面之前最好先在控制台把Key申请好、把一个最简单的“显示地图”跑通确认环境没问题再开始碰路线规划。环境问题永远比代码问题更消耗时间。跑通这套流程之后你大概就知道拿天地图实现“导航功能”这件事到底能做到什么程度了。
返回列表