HarmonyOS 鸿蒙Next中使用高德地图 SDK 实现路径规划功能
HarmonyOS 鸿蒙Next中使用高德地图 SDK 实现路径规划功能 在开发导航类应用时,需要实现多种出行方式的路径规划:
- 支持步行、骑行、驾车、公交四种出行方式
- 返回路线距离、预计用时、详细导航步骤
- 驾车路线需要显示路况信息(拥堵状态)
- 公交路线需要显示换乘方案、途经站点
- 返回路线坐标点用于地图上绑制路线
1. 配置高德地图 SDK
在 oh-package.json5 中添加依赖:
{
"dependencies": {
"[@amap](/user/amap)/amap_lbs_search": "^1.0.0",
"[@amap](/user/amap)/amap_lbs_map3d": "^1.0.0"
}
}
2. 定义路线数据模型
// models/RouteModels.ets
import { LatLng } from '[@amap](/user/amap)/amap_lbs_map3d'
import { TMC } from '[@amap](/user/amap)/amap_lbs_search'
/**
* 路线类型
*/
export type RouteType = 'walk' | 'ride' | 'drive' | 'bus'
/**
* 路线步骤
*/
export interface RouteStep {
instruction: string // 导航指令
action: string // 动作(如"左转"、"直行")
distance: number // 距离(米)
duration: number // 时长(秒)
}
/**
* 路线结果
*/
export interface RouteResult {
type: RouteType
distance: number // 总距离(米)
duration: number // 总时长(秒)
steps: RouteStep[] // 导航步骤
polyline: LatLng[] // 路线坐标点(用于绑制)
// 驾车专用
taxiCost?: number // 打车费用
tolls?: number // 过路费
tmcs?: TMC[] // 路况信息
// 公交专用
busLines?: string[] // 公交线路名称
walkDistance?: number // 步行距离
}
3. 创建路线搜索服务
// services/RouteSearchService.ets
import {
RouteSearchV2,
WalkRouteQueryV2,
DriveRouteQueryV2,
RideRouteQueryV2,
BusRouteQueryV2,
WalkRouteResultV2,
DriveRouteResultV2,
RideRouteResultV2,
BusRouteResultV2,
FromAndTo,
LatLonPoint,
DrivingStrategy,
AMapException,
OnRouteSearchListenerV2,
RouteSearch
} from '[@amap](/user/amap)/amap_lbs_search'
import { LatLng } from '[@amap](/user/amap)/amap_lbs_map3d'
import { RouteResult, RouteStep } from '../models/RouteModels'
/**
* 路线搜索回调
*/
export interface RouteSearchCallback {
onSuccess: (routes: RouteResult[]) => void
onError: (message: string) => void
}
/**
* 路线搜索服务类
*/
export class RouteSearchService {
private routeSearch?: RouteSearchV2
private context: Context
private callback?: RouteSearchCallback
constructor(context: Context) {
this.context = context
}
}
4. 实现步行路线搜索
/**
* 搜索步行路线
*/
searchWalkRoute(start: LatLonPoint, end: LatLonPoint, callback: RouteSearchCallback): void {
this.callback = callback
console.info(`[RouteSearch] 🚶 开始搜索步行路线`)
console.info(` 起点: ${start.getLatitude()}, ${start.getLongitude()}`)
console.info(` 终点: ${end.getLatitude()}, ${end.getLongitude()}`)
this.routeSearch = new RouteSearchV2(this.context)
this.routeSearch.setRouteSearchListener(this.createWalkListener())
const fromAndTo = new FromAndTo(start, end)
const query = new WalkRouteQueryV2(fromAndTo)
query.setShowFields(0b0011111) // 返回所有字段
this.routeSearch.calculateWalkRouteAsyn(query)
}
/**
* 创建步行路线监听器
*/
private createWalkListener(): OnRouteSearchListenerV2 {
return {
onWalkRouteSearched: (result: WalkRouteResultV2, errorCode: number) => {
if (errorCode === AMapException.CODE_AMAP_SUCCESS) {
const paths = result.getPaths()
if (paths && paths.length > 0) {
const routeResults: RouteResult[] = []
for (const path of paths) {
const steps: RouteStep[] = []
const pathSteps = path.getSteps()
if (pathSteps) {
for (const step of pathSteps) {
steps.push({
instruction: step.getInstruction() || '',
action: step.getAction() || '',
distance: step.getDistance() || 0,
duration: step.getDuration() || 0
})
}
}
// 获取路线坐标点
const polylinePoints: LatLng[] = []
const polylineData = path.getPolyline()
if (polylineData) {
for (const point of polylineData) {
polylinePoints.push(new LatLng(point.getLatitude(), point.getLongitude()))
}
}
routeResults.push({
type: 'walk',
distance: path.getDistance() || 0,
duration: path.getDuration() || 0,
steps: steps,
polyline: polylinePoints
})
}
console.info(`[RouteSearch] ✅ 找到 ${routeResults.length} 条步行路线`)
this.callback?.onSuccess(routeResults)
} else {
this.callback?.onError('未找到步行路线')
}
} else {
this.callback?.onError(`路线搜索失败,错误码: ${errorCode}`)
}
},
// 其他回调留空
onDriveRouteSearched: () => {},
onRideRouteSearched: () => {},
onBusRouteSearched: () => {}
}
}
5. 实现驾车路线搜索
/**
* 搜索驾车路线
* @param strategy 驾车策略(可选)
*/
searchDriveRoute(
start: LatLonPoint,
end: LatLonPoint,
callback: RouteSearchCallback,
strategy: number = DrivingStrategy.DEFAULT.getValue()
): void {
this.callback = callback
console.info(`[RouteSearch] 🚗 开始搜索驾车路线(策略: ${strategy})`)
this.routeSearch = new RouteSearchV2(this.context)
this.routeSearch.setRouteSearchListener(this.createDriveListener())
const fromAndTo = new FromAndTo(start, end)
const query = new DriveRouteQueryV2(fromAndTo, strategy, undefined, undefined, "")
query.setShowFields(0b0011111)
this.routeSearch.calculateDriveRouteAsyn(query)
}
/**
* 创建驾车路线监听器
*/
private createDriveListener(): OnRouteSearchListenerV2 {
return {
onDriveRouteSearched: (result: DriveRouteResultV2 | undefined, errorCode: number) => {
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const paths = result.getPaths()
if (paths && paths.length > 0) {
const routeResults: RouteResult[] = []
for (const path of paths) {
const steps: RouteStep[] = []
const tmcs: TMC[] = []
const pathSteps = path.getSteps()
if (pathSteps) {
for (const step of pathSteps) {
const navi = step.getNavi()
steps.push({
instruction: step.getInstruction() || '',
action: navi?.getAction() || '',
distance: this.parseDistanceFromInstruction(step.getInstruction() || ''),
duration: 0
})
// 提取路况信息(TMC)
const tmcList = step.getTMCs()
if (tmcList) {
for (const tmc of tmcList) {
tmcs.push(tmc)
}
}
}
}
const polylinePoints: LatLng[] = []
const polylineData = path.getPolyline()
if (polylineData) {
for (const point of polylineData) {
polylinePoints.push(new LatLng(point.getLatitude(), point.getLongitude()))
}
}
routeResults.push({
type: 'drive',
distance: path.getDistance() || 0,
duration: path.getCost()?.getDuration() || 0,
steps: steps,
polyline: polylinePoints,
taxiCost: Math.floor(result.getTaxiCost() || 0),
tolls: 0,
tmcs: tmcs
})
}
console.info(`[RouteSearch] ✅ 找到 ${routeResults.length} 条驾车路线`)
this.callback?.onSuccess(routeResults)
} else {
this.callback?.onError('未找到驾车路线')
}
} else {
this.callback?.onError(`路线搜索失败,错误码: ${errorCode}`)
}
},
onWalkRouteSearched: () => {},
onRideRouteSearched: () => {},
onBusRouteSearched: () => {}
}
}
6. 实现骑行路线搜索
/**
* 搜索骑行路线
*/
searchRideRoute(start: LatLonPoint, end: LatLonPoint, callback: RouteSearchCallback): void {
this.callback = callback
console.info(`[RouteSearch] 🚴 开始搜索骑行路线`)
this.routeSearch = new RouteSearchV2(this.context)
this.routeSearch.setRouteSearchListener(this.createRideListener())
const fromAndTo = new FromAndTo(start, end)
const query = new RideRouteQueryV2(fromAndTo)
query.setShowFields(0b0011111)
this.routeSearch.calculateRideRouteAsyn(query)
}
/**
* 创建骑行路线监听器
*/
private createRideListener(): OnRouteSearchListenerV2 {
return {
onRideRouteSearched: (result: RideRouteResultV2, errorCode: number) => {
if (errorCode === AMapException.CODE_AMAP_SUCCESS) {
const paths = result.getPaths()
if (paths && paths.length > 0) {
const routeResults: RouteResult[] = paths.map(path => {
const steps: RouteStep[] = []
const pathSteps = path.getSteps()
if (pathSteps) {
for (const step of pathSteps) {
steps.push({
instruction: step.getInstruction() || '',
action: step.getAction() || '',
distance: step.getDistance() || 0,
duration: step.getDuration() || 0
})
}
}
const polylinePoints: LatLng[] = []
const polylineData = path.getPolyline()
if (polylineData) {
for (const point of polylineData) {
polylinePoints.push(new LatLng(point.getLatitude(), point.getLongitude()))
}
}
return {
type: 'ride' as const,
distance: path.getDistance() || 0,
duration: path.getDuration() || 0,
steps: steps,
polyline: polylinePoints
}
})
console.info(`[RouteSearch] ✅ 找到 ${routeResults.length} 条骑行路线`)
this.callback?.onSuccess(routeResults)
} else {
this.callback?.onError('未找到骑行路线')
}
} else {
this.callback?.onError(`路线搜索失败,错误码: ${errorCode}`)
}
},
onWalkRouteSearched: () => {},
onDriveRouteSearched: () => {},
onBusRouteSearched: () => {}
}
}
7. 实现公交路线搜索
/**
* 搜索公交路线
* @param cityCode 城市代码(如北京 '010')
*/
searchBusRoute(
start: LatLonPoint,
end: LatLonPoint,
callback: RouteSearchCallback,
cityCode: string
): void {
this.callback = callback
console.info(`[RouteSearch] 🚌 开始搜索公交路线(城市: ${cityCode})`)
this.routeSearch = new RouteSearchV2(this.context)
this.routeSearch.setRouteSearchListener(this.createBusListener())
const fromAndTo = new FromAndTo(start, end)
const query = new BusRouteQueryV2(fromAndTo, RouteSearch.BusDefault, cityCode, 0)
query.setCityd(cityCode) // 目的地城市代码
query.setShowFields(0b0011111)
this.routeSearch.calculateBusRouteAsyn(query)
}
/**
* 创建公交路线监听器
*/
private createBusListener(): OnRouteSearchListenerV2 {
return {
onBusRouteSearched: (result: BusRouteResultV2 | undefined, errorCode: number) => {
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const paths = result.getPaths()
if (paths && paths.length > 0) {
const routeResults: RouteResult[] = []
for (const path of paths) {
const steps: RouteStep[] = []
const polylinePoints: LatLng[] = []
const busLineNames: string[] = []
let totalWalkDistance = 0
const busSteps = path.getSteps()
if (busSteps) {
for (const busStep of busSteps) {
// 步行段
const walk = busStep.getWalk()
if (walk) {
const walkDistance = walk.getDistance() || 0
totalWalkDistance += walkDistance
const walkSteps = walk.getSteps()
if (walkSteps) {
for (const walkStep of walkSteps) {
steps.push({
instruction: `步行 ${walkStep.getInstruction() || ''}`,
action: 'walk',
distance: walkStep.getDistance() || 0,
duration: walkStep.getDuration() || 0
})
}
}
}
// 公交/地铁段
const busLines = busStep.getBusLines()
if (busLines && busLines.length > 0) {
for (const busLine of busLines) {
const lineName = busLine.getBusLineName() || ''
const departure = busLine.getDepartureBusStation()?.getBusStationName() || ''
const arrival = busLine.getArrivalBusStation()?.getBusStationName() || ''
const passCount = busLine.getPassStationNum() || 0
busLineNames.push(lineName)
steps.push({
instruction: `乘坐 ${lineName},${departure} 上车,${arrival} 下车,途经 ${passCount} 站`,
action: 'bus',
distance: busLine.getDistance() || 0,
duration: busLine.getDuration() || 0
})
// 获取公交线路坐标
const busPolyline = busLine.getPolyline()
if (busPolyline) {
for (const point of busPolyline) {
polylinePoints.push(new LatLng(point.getLatitude(), point.getLongitude()))
}
}
}
}
}
}
routeResults.push({
type: 'bus',
distance: path.getDistance() || 0,
duration: path.getDuration() || 0,
steps: steps,
polyline: polylinePoints,
busLines: busLineNames,
walkDistance: totalWalkDistance
})
}
console.info(`[RouteSearch] ✅ 找到 ${routeResults.length} 条公交路线`)
this.callback?.onSuccess(routeResults)
} else {
this.callback?.onError('未找到公交路线')
}
} else {
this.callback?.onError(`路线搜索失败,错误码: ${errorCode}`)
}
},
onWalkRouteSearched: () => {},
onDriveRouteSearched: () => {},
onRideRouteSearched: () => {}
}
}
8. 在页面中使用
// pages/RoutePlanPage.ets
import { RouteSearchService, RouteSearchCallback } from '../services/RouteSearchService'
import { RouteResult, RouteType } from '../models/RouteModels'
import { LatLonPoint } from '[@amap](/user/amap)/amap_lbs_search'
[@Entry](/user/Entry)
[@Component](/user/Component)
struct RoutePlanPage {
[@State](/user/State) selectedType: RouteType = 'walk'
[@State](/user/State) routeResult: RouteResult | null = null
[@State](/user/State) isSearching: boolean = false
private routeService?: RouteSearchService
// 起终点
private start = new LatLonPoint(39.9042, 116.4074) // 天安门
private end = new LatLonPoint(39.9163, 116.3972) // 北海公园
aboutToAppear(): void {
this.routeService = new RouteSearchService(getContext(this))
}
build() {
Column({ space: 16 }) {
// 出行方式选择
Row({ space: 8 }) {
ForEach(['walk', 'ride', 'drive', 'bus'], (type: RouteType) => {
Button(this.getTypeLabel(type))
.backgroundColor(this.selectedType === type ? '#A9846A' : '#E0E0E0')
.fontColor(this.selectedType === type ? '#FFFFFF' : '#333333')
.onClick(() => {
this.selectedType = type
this.searchRoute()
})
})
}
// 搜索状态
if (this.isSearching) {
LoadingProgress().width(40).height(40)
}
// 路线结果
if (this.routeResult) {
Column({ space: 8 }) {
Text(`总距离: ${this.formatDistance(this.routeResult.distance)}`)
Text(`预计用时: ${this.formatDuration(this.routeResult.duration)}`)
if (this.routeResult.taxiCost) {
Text(`预计打车费: ¥${this.routeResult.taxiCost}`)
}
Divider()
// 导航步骤
List() {
ForEach(this.routeResult.steps, (step: RouteStep, index: number) => {
ListItem() {
Row({ space: 8 }) {
Text(`${index + 1}`)
.width(24)
.textAlign(TextAlign.Center)
Text(step.instruction)
.更多关于HarmonyOS 鸿蒙Next中使用高德地图 SDK 实现路径规划功能的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中实现高德地图SDK路径规划,首先需在AppGallery Connect配置应用并获取API Key。通过DevEco Studio集成高Maps SDK,在module.json5中声明ohos.permission.LOCATION等权限。使用@amap/amap-harmonyos包,调用AMapNavi的calculateDriveRoute方法传入起点、终点坐标及策略参数。通过回调处理RouteResult返回的路径信息,可结合Map组件进行可视化绘制。注意SDK需使用HarmonyOS专用版本,并遵循官方坐标转换规范。
在HarmonyOS Next中使用高德地图SDK实现路径规划功能,核心是调用RouteSearch模块。以下是关键步骤和代码要点:
-
初始化与权限配置 在
module.json5中声明ohos.permission.LOCATION位置权限,并配置高德地图的access_token。 -
路线搜索参数设置 根据出行方式创建对应的
RouteSearch.FromAndTo(起终点)和搜索参数:- 驾车:
DrivingRoutePlanParam,需设置drivingStrategy(策略)并启用setOpenTraffic(true)获取路况。 - 公交:
TransitRoutePlanParam,设置transitStrategy(如最经济、最快捷)。 - 步行/骑行:
WalkingRoutePlanParam/RidingRoutePlanParam。
示例(驾车):
let fromAndTo: routeSearch.FromAndTo = { from: { lat: 39.9, lon: 116.3 }, to: { lat: 40.0, lon: 116.4 } }; let param: routeSearch.DrivingRoutePlanParam = { fromAndTo: fromAndTo, drivingStrategy: routeSearch.DrivingStrategy.FASTEST_SHORT_DISTANCE }; - 驾车:
-
执行搜索并解析结果 调用
routeSearch.calculateRoute(),在回调中处理结果:- 从
RoutePlanResult获取paths(路线数组),每条path包含distance(距离)、duration(用时)。 - 驾车路线:从
DrivingPath的steps读取traffic(路况状态:0畅通、1缓行、2拥堵)。 - 公交路线:从
TransitPath的segments获取busLines(公交线路)及boarding/alighting站点信息。 - 坐标点:所有出行方式的
steps均提供polyline(坐标串),可用于地图绘制。
- 从
-
地图绘制 将
polyline坐标串转换为Map模块的Polyline对象,并添加到地图图层。
注意事项:
- 公交/驾车需分别使用专属参数类,确保返回完整数据。
- 路径规划为网络请求,需在主线程外执行。
- 坐标点需按高德
GCJ-02坐标系处理,与HarmonyOS地图匹配。
通过以上步骤,可完整实现多方式路径规划、数据解析及地图可视化。

