别再手动拼接坐标了!用uniapp+高德地图API,5分钟搞定跨城市驾车路线规划

张开发
2026/4/12 0:50:30 15 分钟阅读

分享文章

别再手动拼接坐标了!用uniapp+高德地图API,5分钟搞定跨城市驾车路线规划
别再手动拼接坐标了用uniapp高德地图API5分钟搞定跨城市驾车路线规划每次接到需要实现跨城市路线规划的需求时最头疼的就是处理那些密密麻麻的坐标点数据。手动拼接、计算边界、调整视野...这些繁琐的操作不仅耗时耗力还容易出错。其实借助uniapp的map组件和高德地图API我们完全可以摆脱这些体力活让代码自动完成这些复杂计算。1. 为什么需要自动化路线规划传统的手动处理路线数据存在几个明显痛点数据量大一条跨城市路线可能包含数百个坐标点精度要求高每个点的经纬度都需要精确到小数点后6位边界计算复杂要确保地图能完整显示整条路线维护困难路线变更时需要重新计算所有数据// 典型的手动坐标数据格式 const manualPoints [ {longitude: 120.123456, latitude: 30.123456}, {longitude: 120.123567, latitude: 30.123567}, // ...可能有上百个这样的点 ]高德地图的路径规划API可以一次性返回整条路线的所有关键点配合uniapp的map组件我们可以实现自动获取起点和终点的经纬度自动计算最优路线自动处理polyline数据格式智能计算地图显示边界2. 快速搭建开发环境2.1 获取高德地图开发者密钥首先需要在高德开放平台申请Web服务API密钥访问高德开放平台注册开发者账号进入应用管理创建新应用选择Web服务类型获取生成的Key提示在小程序中使用时记得将https://restapi.amap.com添加到小程序域名白名单中。2.2 初始化uniapp项目创建一个基本的uniapp项目结构project/ ├── pages/ │ └── map/ │ ├── index.vue │ └── map.js ├── static/ └── manifest.json安装必要的依赖npm install dcloudio/uni-ui --save3. 核心实现步骤3.1 基础地图展示首先在页面中引入map组件template view classcontainer map idrouteMap :longitudecenter.longitude :latitudecenter.latitude :markersmarkers :polylinepolyline :include-pointsbounds markertaphandleMarkerTap stylewidth: 100%; height: 80vh; /map /view /template初始化地图中心点和标记export default { data() { return { center: { longitude: 120.153576, latitude: 30.287459 }, markers: [ { id: 1, latitude: 30.287459, longitude: 120.153576, iconPath: /static/start.png, width: 30, height: 30, callout: { content: 起点, display: ALWAYS } } ], polyline: [], bounds: [] } } }3.2 智能路线规划实现获取地点经纬度async function getLocation(address, key) { try { const res await uni.request({ url: https://restapi.amap.com/v3/geocode/geo?address${encodeURIComponent(address)}key${key} }); if (res[1].data.geocodes.length 0) { return res[1].data.geocodes[0].location; // 返回经度,纬度字符串 } throw new Error(地址解析失败); } catch (error) { console.error(获取位置失败:, error); return null; } }获取驾驶路线async function getDrivingRoute(origin, destination, key) { try { const res await uni.request({ url: https://restapi.amap.com/v3/direction/driving?origin${origin}destination${destination}key${key} }); return res[1].data.route.paths[0].steps; } catch (error) { console.error(获取路线失败:, error); return null; } }数据清洗与边界计算这是最核心的部分自动处理polyline数据并计算最佳显示范围function processRouteData(steps) { const points []; let minLat Infinity, maxLat -Infinity; let minLng Infinity, maxLng -Infinity; steps.forEach(step { const coords step.polyline.split(;); coords.forEach(coord { const [lng, lat] coord.split(,).map(Number); points.push({ longitude: lng, latitude: lat }); // 更新边界范围 minLat Math.min(minLat, lat); maxLat Math.max(maxLat, lat); minLng Math.min(minLng, lng); maxLng Math.max(maxLng, lng); }); }); // 计算中心点 const center { longitude: (minLng maxLng) / 2, latitude: (minLat maxLat) / 2 }; // 添加5%的边界缓冲 const latBuffer (maxLat - minLat) * 0.05; const lngBuffer (maxLng - minLng) * 0.05; const bounds [ { latitude: minLat - latBuffer, longitude: minLng - lngBuffer }, { latitude: maxLat latBuffer, longitude: maxLng lngBuffer } ]; return { points, center, bounds, polyline: [{ points, width: 4, arrowLine: true, color: #1890FF, }] }; }3.3 完整流程整合将上述功能整合成一个完整的路线规划方法async function planRoute(startAddress, endAddress, key) { // 1. 获取起点终点坐标 const startLocation await getLocation(startAddress, key); const endLocation await getLocation(endAddress, key); if (!startLocation || !endLocation) { uni.showToast({ title: 地址解析失败, icon: none }); return; } // 2. 获取路线数据 const steps await getDrivingRoute(startLocation, endLocation, key); if (!steps || steps.length 0) { uni.showToast({ title: 路线规划失败, icon: none }); return; } // 3. 处理数据 const { points, center, bounds, polyline } processRouteData(steps); // 4. 更新地图显示 this.center center; this.bounds bounds; this.polyline polyline; // 5. 更新标记 this.markers [ { id: 1, latitude: parseFloat(startLocation.split(,)[1]), longitude: parseFloat(startLocation.split(,)[0]), iconPath: /static/start.png, width: 30, height: 30, callout: { content: 起点, display: ALWAYS } }, { id: 2, latitude: parseFloat(endLocation.split(,)[1]), longitude: parseFloat(endLocation.split(,)[0]), iconPath: /static/end.png, width: 30, height: 30, callout: { content: 终点, display: ALWAYS } } ]; }4. 高级功能扩展4.1 实时导航功能添加标记点击事件实现跳转到系统地图导航function handleMarkerTap(e) { const markerId e.detail.markerId; const marker this.markers.find(m m.id markerId); if (marker) { uni.showActionSheet({ itemList: [使用系统地图导航], success: () { uni.openLocation({ latitude: marker.latitude, longitude: marker.longitude, name: marker.callout?.content || 目的地 }); } }); } }4.2 路线优化建议根据高德API返回的数据我们可以提供一些优化建议避开拥堵检查返回的traffic_condition字段节省费用比较不同路线的tolls和distance时间预估使用duration字段显示预计到达时间function analyzeRoute(steps) { let totalDistance 0; // 总距离(米) let totalDuration 0; // 总时间(秒) let tolls 0; // 总收费(元) let trafficLights 0; // 红绿灯数量 steps.forEach(step { totalDistance step.distance; totalDuration step.duration; tolls step.tolls || 0; trafficLights step.traffic_light_count || 0; }); return { distance: (totalDistance / 1000).toFixed(1) 公里, duration: Math.ceil(totalDuration / 60) 分钟, tolls: tolls 0 ? tolls 元 : 免费, trafficLights: trafficLights 个红绿灯 }; }4.3 多路线选择高德API支持返回多条可行路线我们可以让用户选择async function getMultipleRoutes(origin, destination, key) { const res await uni.request({ url: https://restapi.amap.com/v3/direction/driving?origin${origin}destination${destination}key${key}strategy0|1|2 }); return res[1].data.route.paths.map((path, index) { const { steps } path; const { points, bounds } processRouteData(steps); return { id: index 1, name: 路线${index 1}, distance: (path.distance / 1000).toFixed(1) 公里, duration: Math.ceil(path.duration / 60) 分钟, tolls: path.tolls 0 ? path.tolls 元 : 免费, points, bounds }; }); }在页面上显示路线选择菜单view classroute-options view v-foroption in routeOptions :keyoption.id clickselectRoute(option) classroute-option text{{option.name}}: {{option.distance}} / {{option.duration}}/text text v-ifoption.tolls ! 免费(收费: {{option.tolls}})/text /view /view5. 性能优化与常见问题5.1 地图渲染性能优化当路线特别长时可能会遇到性能问题。以下是几个优化建议减少点数对polyline点进行抽样简化分段加载特别长的路线可以分段请求和渲染延迟渲染等地图初始化完成后再加载路线function simplifyPoints(points, tolerance 0.0001) { if (points.length 100) return points; // 使用Douglas-Peucker算法简化点集 const simplified [points[0]]; let lastPoint points[0]; for (let i 1; i points.length - 1; i) { const point points[i]; const distance Math.sqrt( Math.pow(point.longitude - lastPoint.longitude, 2) Math.pow(point.latitude - lastPoint.latitude, 2) ); if (distance tolerance) { simplified.push(point); lastPoint point; } } simplified.push(points[points.length - 1]); return simplified; }5.2 常见问题排查问题现象可能原因解决方案地图不显示容器没有设置宽高确保map组件有明确的宽高样式路线不显示polyline格式错误检查points数组中的经纬度是否为数字标记不显示图片路径错误使用绝对路径或base64图片API请求失败密钥无效或域名未配置检查密钥和域名白名单配置路线显示不全边界计算错误检查bounds数组是否包含所有点5.3 跨平台兼容性处理uniapp的map组件在不同平台上有细微差异小程序需要配置域名白名单H5可能需要引入额外的地图JS库App需要配置高德地图SDK// 平台特定代码示例 function initMap() { // #ifdef MP-WEIXIN console.log(小程序环境初始化); // #endif // #ifdef H5 console.log(H5环境初始化); // #endif // #ifdef APP-PLUS console.log(App环境初始化); // #endif }在实际项目中处理一个从北京中关村到上海陆家嘴的跨城路线规划需求时高德API返回了包含1200多个坐标点的数据。手动处理这些数据几乎是不可能的任务而通过本文的自动化方案整个处理过程不到1秒就完成了而且地图自动缩放到刚好能显示整条路线的最佳视野。

更多文章