前言
最近需要实现一个需求,通过起点终点的名称实现路径规划,还需要对特定的点进行标记。最后使用高德提供的API+uniapp的map组件进行实现。
1. 实现思路
使用uniapp的map组件实现路径规划,需要使用map中的属性polyline,而polyline需要知道途径点的坐标信息。我们就需要使用高德提供的API获取起始点的经纬度,去获取途径点经纬度,就可以实现路径规划功能。
在线体验:
2. 实现准备工作
- 首先你需要去申请一个属于自己的高德地图key,高德开放平台应用管理,成为开发者,创建应用,类型是
web服务,就可以得到key - 需要使用的API文档高德开放平台API文档
- 通过地理编码获取经纬度API
- 路径规划API
- 需要添加小程序域名白名单
https://restapi.amap.com
3. 具体代码实现
3.1 map基本使用
新建一个uniapp的空白页 使用map组件渲染地图,注意地图组件需要设置宽高。
<map id='map' :longitude="118.045616" :latitude="24.366646" :markers="markers"></map>
const markers = [{
latitude: 24.366646,
longitude: 118.045616,
width: 40,
height: 40,
callout: {
content: '起点',
display:'ALWAYS'
},
iconPath: '../../../../static/addrs.png'
}]
恭喜你,完成了地图的基本使用。
路径规划需要使用polyline,对应的使用文档如下:
3.2 获取路径规划经纬度
我们需要借助高德地图的路径规划查询获取到全部的路径规划,已经知道起点终点:
- 获取高德key
2. 使用API获取数据
根据地址获取经纬度
// 获取地理位置
const getLocation = (address: string): Promise<string> => {
return new Promise((resolve) => {
uni.request({
url: `https://restapi.amap.com/v3/geocode/geo?address=${address}&key=${key}`,
success: (res) => {
if (res.data.geocodes.length) {
resolve(res.data.geocodes[0].location)
}
}
});
})
}
获取起始点和终点的路径规划:
const getDriving = async () => {
const origin = await getLocation('杭州三墩')
const destination = await getLocation('萧山机场')
uni.request({
url: `https://restapi.amap.com/v3/direction/driving?origin=${origin}&destination=${destination}&key=${key}`,
success: (res) => {
const data = res.data.route
if (data.paths?.[0]?.steps) {
washData(data.paths[0].steps)
}
}
});
}
获取到全部路径规划的数据,但是还是要洗一下数据,需要对应polyline格式数据。
let polyline = ref([])
const washData = (steps) => {
let points = []
steps.forEach(item => {
const polen = item.polyline.split(';')
polen.forEach(vv => {
let splits = vv.split(',')
points.push({
longitude: parseFloat(splits[0]),
latitude: parseFloat(splits[1])
})
})
})
polyline.value = [{
points: points,
width: 3,
arrowLine: true,
arrowIconPath: true,
color: '#204CF1',
}]
}
使用
<map id='map' :longitude="118.045616" :latitude="24.366646" :markers="markers" :polyline="polyline"></map>
至此路线图就完成,但是有一点问题,路线没有缩小可以直接预览全部。
3.3 处理居中问题
可以使用include-points进行缩放视野以包含所有给定的坐标点
可以在清洗数据时添加边界点
const bounds = ref([])
const washData = (steps) => {
let points = []
let minLat = Infinity, maxLat = -Infinity
let minLng = Infinity, maxLng = -Infinity
steps.forEach(item => {
const polen = item.polyline.split(';')
polen.forEach(vv => {
const [lngStr, latStr] = vv.split(',')
const lng = parseFloat(lngStr)
const lat = parseFloat(latStr)
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)
})
})
// 设置地图中心点为路线中心(但不添加标记)
longitude.value = (minLng + maxLng) / 2
latitude.value = (minLat + maxLat) / 2
// 添加边界缓冲
const latBuffer = (maxLat - minLat) * 0.05
const lngBuffer = (maxLng - minLng) * 0.05
bounds.value = [
{ latitude: minLat - latBuffer, longitude: minLng - lngBuffer },
{ latitude: maxLat + latBuffer, longitude: maxLng + lngBuffer }
]
polyline.value = [{
points,
width: 4,
arrowLine: true,
color: '#204CF1',
}]
}
使用
<map id="map" :longitude="longitude" :latitude="latitude" :markers="markers" :polyline="polyline"
:include-points="bounds"></map>
3.4 添加起点终点点击导航
使用markertap事件,可以进行弹框导航。
具体实现:
<map id="map" :longitude="longitude" :latitude="latitude" :markers="markers" :polyline="polyline" :include-points="bounds" @markertap="handleMarker"></map>
<div v-if="showMarker" class="bottom flex justify-end items-center">
<wd-button size="small" class="text-12px" @click="openMap">
导航
</wd-button>
</div>
const handleMarker = (e) => {
const id = e.detail.markerId
const find = markers.find(item => item.id === id)
currentLocation.value.latitude = find?.latitude
currentLocation.value.longitude = find?.longitude
showMarker.value = !showMarker.value
}
const openMap = () => {
uni.openLocation({
latitude: currentLocation.value.latitude,
longitude: currentLocation.value.longitude,
// scale: 28
});
}
使用uni.openLocation进行导航即可。
总结
最后总结一下:整体流程就是获取高德的key->调用接口获取起始点和终点坐标->调用接口获取路径规划->清洗数据(获取边界以获取缩放视野)-> 渲染 -> 添加点导航,至此就完成了全部流程。希望能对你有所帮助,如有错误,请指正O^O!