[鸿蒙2025领航者闯关]HarmonyOS中开发高德地图第八篇:路线规划功能
本篇教程将学习如何使用高德地图实现驾车、步行、骑行等路线规划功能。
·
第八篇:路线规划功能
本篇教程将学习如何使用高德地图实现驾车、步行、骑行等路线规划功能。
学习目标
- 实现驾车路线规划
- 实现步行路线规划
- 实现骑行路线规划
- 在地图上绑制规划路线
- 显示路线详情信息
1. 路线规划类型
| 类型 | 类名 | 说明 |
|---|---|---|
| 驾车 | DriveRouteQuery |
汽车导航路线 |
| 步行 | WalkRouteQuery |
步行路线 |
| 骑行 | RideRouteQuery |
骑行路线 |
| 公交 | BusRouteQuery |
公共交通路线 |
| 货车 | TruckRouteQuery |
货车路线 |
2. 核心类说明
| 类名 | 说明 |
|---|---|
RouteSearch |
路线搜索核心类 |
FromAndTo |
起终点配置 |
LatLonPoint |
坐标点 |
DriveRouteResult |
驾车结果 |
WalkRouteResult |
步行结果 |
DrivePath |
驾车路径 |
DriveStep |
驾车步骤 |
3. 完整代码示例
创建文件 entry/src/main/ets/pages/Demo07_Route.ets:
import {
AMap,
MapView,
MapViewComponent,
MapViewManager,
MapViewCreateCallback,
CameraUpdateFactory,
LatLng,
LatLngBounds,
Marker,
MarkerOptions,
Polyline,
PolylineOptions,
BitmapDescriptorFactory
} from '@amap/amap_lbs_map3d';
import {
RouteSearch,
DriveRouteQuery,
DriveRouteResult,
WalkRouteQuery,
WalkRouteResult,
RideRouteQuery,
RideRouteResult,
BusRouteResult,
FromAndTo,
LatLonPoint,
OnRouteSearchListener,
AMapException,
DrivePath,
DriveStep,
WalkPath,
WalkStep,
RidePath,
RideStep
} from '@amap/amap_lbs_search';
const MAP_VIEW_NAME = 'RouteDemo';
/**
* 路线类型
*/
type RouteType = 'drive' | 'walk' | 'ride';
/**
* 路线步骤信息
*/
interface RouteStepInfo {
instruction: string;
distance: number;
duration: number;
}
@Entry
@Component
struct Demo07_Route {
private mapView: MapView | undefined = undefined;
private aMap: AMap | undefined = undefined;
private routeSearch: RouteSearch | undefined = undefined;
private routePolyline: Polyline | undefined = undefined;
private startMarker: Marker | undefined = undefined;
private endMarker: Marker | undefined = undefined;
@State isMapReady: boolean = false;
@State routeType: RouteType = 'drive';
@State isSearching: boolean = false;
@State routeInfo: string = '';
@State routeSteps: RouteStepInfo[] = [];
// 起终点坐标
private startPoint: LatLonPoint = new LatLonPoint(39.942295, 116.335891); // 北京西站
private endPoint: LatLonPoint = new LatLonPoint(39.995576, 116.481288); // 望京SOHO
/**
* 路线搜索回调
*/
private routeSearchListener: OnRouteSearchListener = {
// 驾车路线回调
onDriveRouteSearched: (result: DriveRouteResult | undefined, errorCode: number) => {
this.isSearching = false;
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const paths = result.getPaths();
if (paths && paths.length > 0) {
const path = paths[0] as DrivePath;
this.showDriveRoute(path, result);
} else {
this.routeInfo = '未找到驾车路线';
}
} else {
this.routeInfo = `驾车路线查询失败: ${errorCode}`;
}
},
// 步行路线回调
onWalkRouteSearched: (result: WalkRouteResult | undefined, errorCode: number) => {
this.isSearching = false;
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const paths = result.getPaths();
if (paths && paths.length > 0) {
const path = paths[0] as WalkPath;
this.showWalkRoute(path);
} else {
this.routeInfo = '未找到步行路线';
}
} else {
this.routeInfo = `步行路线查询失败: ${errorCode}`;
}
},
// 骑行路线回调
onRideRouteSearched: (result: RideRouteResult | undefined, errorCode: number) => {
this.isSearching = false;
if (errorCode === AMapException.CODE_AMAP_SUCCESS && result) {
const paths = result.getPaths();
if (paths && paths.length > 0) {
const path = paths[0] as RidePath;
this.showRideRoute(path);
} else {
this.routeInfo = '未找到骑行路线';
}
} else {
this.routeInfo = `骑行路线查询失败: ${errorCode}`;
}
},
// 公交路线回调
onBusRouteSearched: (result: BusRouteResult | undefined, errorCode: number) => {
this.isSearching = false;
this.routeInfo = '公交路线功能待实现';
}
};
private mapViewCreateCallback: MapViewCreateCallback =
(mapview: MapView | undefined, mapViewName: string | undefined) => {
if (!mapview || mapViewName !== MAP_VIEW_NAME) return;
this.mapView = mapview;
this.mapView.onCreate();
this.mapView.getMapAsync((map: AMap) => {
this.aMap = map;
this.isMapReady = true;
// 设置初始视野
const center = new LatLng(39.97, 116.41);
map.moveCamera(CameraUpdateFactory.newLatLngZoom(center, 11));
// 启用控件
map.getUiSettings()?.setZoomControlsEnabled(true);
// 添加起终点标记
this.addStartEndMarkers();
// 地图长按设置终点
map.setOnMapLongClickListener((point: LatLng) => {
this.endPoint = new LatLonPoint(point.latitude, point.longitude);
this.updateEndMarker();
this.routeInfo = '终点已更新,点击搜索查看路线';
});
});
};
/**
* 添加起终点标记
*/
private addStartEndMarkers(): void {
if (!this.aMap) return;
// 起点标记
const startOptions = new MarkerOptions();
startOptions.setPosition(new LatLng(this.startPoint.getLatitude(), this.startPoint.getLongitude()));
startOptions.setTitle('起点');
startOptions.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN));
startOptions.setAnchor(0.5, 1.0);
this.startMarker = this.aMap.addMarker(startOptions);
// 终点标记
const endOptions = new MarkerOptions();
endOptions.setPosition(new LatLng(this.endPoint.getLatitude(), this.endPoint.getLongitude()));
endOptions.setTitle('终点');
endOptions.setIcon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
endOptions.setAnchor(0.5, 1.0);
this.endMarker = this.aMap.addMarker(endOptions);
}
/**
* 更新终点标记
*/
private updateEndMarker(): void {
if (this.endMarker) {
this.endMarker.setPosition(new LatLng(this.endPoint.getLatitude(), this.endPoint.getLongitude()));
}
}
/**
* 搜索路线
*/
private searchRoute(): void {
if (!this.routeSearch) return;
this.isSearching = true;
this.routeInfo = '正在搜索路线...';
this.routeSteps = [];
// 清除之前的路线
this.clearRouteLine();
// 创建起终点
const fromAndTo = new FromAndTo(this.startPoint, this.endPoint);
switch (this.routeType) {
case 'drive':
this.searchDriveRoute(fromAndTo);
break;
case 'walk':
this.searchWalkRoute(fromAndTo);
break;
case 'ride':
this.searchRideRoute(fromAndTo);
break;
}
}
/**
* 搜索驾车路线
*/
private searchDriveRoute(fromAndTo: FromAndTo): void {
const query = new DriveRouteQuery(
fromAndTo,
RouteSearch.DrivingDefault, // 驾车策略
undefined, // 途经点
undefined, // 避让区域
'' // 避让道路
);
query.setExtensions(RouteSearch.EXTENSIONS_ALL);
this.routeSearch?.calculateDriveRouteAsyn(query);
console.info('[Route] Searching drive route...');
}
/**
* 搜索步行路线
*/
private searchWalkRoute(fromAndTo: FromAndTo): void {
const query = new WalkRouteQuery(fromAndTo);
this.routeSearch?.calculateWalkRouteAsyn(query);
console.info('[Route] Searching walk route...');
}
/**
* 搜索骑行路线
*/
private searchRideRoute(fromAndTo: FromAndTo): void {
const query = new RideRouteQuery(fromAndTo);
this.routeSearch?.calculateRideRouteAsyn(query);
console.info('[Route] Searching ride route...');
}
/**
* 显示驾车路线
*/
private showDriveRoute(path: DrivePath, result: DriveRouteResult): void {
const distance = path.getDistance();
const duration = path.getDuration();
const taxiCost = result.getTaxiCost();
this.routeInfo = `驾车路线\n距离: ${this.formatDistance(distance)}\n时间: ${this.formatDuration(duration)}\n预估打车费: ¥${Math.floor(taxiCost)}`;
// 解析路线步骤
const steps = path.getSteps();
if (steps) {
this.routeSteps = [];
for (let i = 0; i < steps.length; i++) {
const step = steps[i] as DriveStep;
this.routeSteps.push({
instruction: step.getInstruction() || '',
distance: step.getDistance(),
duration: step.getDuration()
});
}
}
// 绘制路线
this.drawRouteLine(path.getSteps(), '#4CAF50');
}
/**
* 显示步行路线
*/
private showWalkRoute(path: WalkPath): void {
const distance = path.getDistance();
const duration = path.getDuration();
this.routeInfo = `步行路线\n距离: ${this.formatDistance(distance)}\n时间: ${this.formatDuration(duration)}`;
// 解析步骤
const steps = path.getSteps();
if (steps) {
this.routeSteps = [];
for (let i = 0; i < steps.length; i++) {
const step = steps[i] as WalkStep;
this.routeSteps.push({
instruction: step.getInstruction() || '',
distance: step.getDistance(),
duration: step.getDuration()
});
}
}
// 绘制路线
this.drawRouteLine(steps, '#2196F3');
}
/**
* 显示骑行路线
*/
private showRideRoute(path: RidePath): void {
const distance = path.getDistance();
const duration = path.getDuration();
this.routeInfo = `骑行路线\n距离: ${this.formatDistance(distance)}\n时间: ${this.formatDuration(duration)}`;
// 解析步骤
const steps = path.getSteps();
if (steps) {
this.routeSteps = [];
for (let i = 0; i < steps.length; i++) {
const step = steps[i] as RideStep;
this.routeSteps.push({
instruction: step.getInstruction() || '',
distance: step.getDistance(),
duration: step.getDuration()
});
}
}
// 绘制路线
this.drawRouteLine(steps, '#FF9800');
}
/**
* 绘制路线
*/
private drawRouteLine(steps: Object[] | undefined, color: string): void {
if (!this.aMap || !steps) return;
// 收集所有坐标点
const points: LatLng[] = [];
for (const step of steps) {
// 获取polyline
const polyline = (step as DriveStep).getPolyline?.() ||
(step as WalkStep).getPolyline?.() ||
(step as RideStep).getPolyline?.();
if (polyline) {
for (const point of polyline) {
points.push(new LatLng(point.getLatitude(), point.getLongitude()));
}
}
}
if (points.length > 0) {
// 绘制折线
const options = new PolylineOptions();
options.setPoints(points);
options.setWidth(12);
options.setColor(this.parseColor(color));
this.routePolyline = this.aMap.addPolyline(options);
// 调整视野
this.fitRouteBounds(points);
}
}
/**
* 清除路线
*/
private clearRouteLine(): void {
if (this.routePolyline) {
this.routePolyline.remove();
this.routePolyline = undefined;
}
}
/**
* 调整地图视野以显示完整路线
*/
private fitRouteBounds(points: LatLng[]): void {
if (!this.aMap || points.length === 0) return;
let minLat = 90, maxLat = -90, minLng = 180, maxLng = -180;
for (const point of points) {
minLat = Math.min(minLat, point.latitude);
maxLat = Math.max(maxLat, point.latitude);
minLng = Math.min(minLng, point.longitude);
maxLng = Math.max(maxLng, point.longitude);
}
const bounds = new LatLngBounds(
new LatLng(minLat, minLng),
new LatLng(maxLat, maxLng)
);
this.aMap.animateCamera(
CameraUpdateFactory.newLatLngBounds(bounds, 80),
500
);
}
/**
* 格式化距离
*/
private formatDistance(meters: number): string {
if (meters < 1000) {
return `${meters}米`;
}
return `${(meters / 1000).toFixed(1)}公里`;
}
/**
* 格式化时间
*/
private formatDuration(seconds: number): string {
if (seconds < 60) {
return `${seconds}秒`;
}
const minutes = Math.floor(seconds / 60);
if (minutes < 60) {
return `${minutes}分钟`;
}
const hours = Math.floor(minutes / 60);
const remainMinutes = minutes % 60;
return `${hours}小时${remainMinutes}分钟`;
}
/**
* 解析颜色值
*/
private parseColor(hex: string): number {
const r = parseInt(hex.slice(1, 3), 16);
const g = parseInt(hex.slice(3, 5), 16);
const b = parseInt(hex.slice(5, 7), 16);
return 0xFF000000 | (r << 16) | (g << 8) | b;
}
aboutToAppear(): void {
MapViewManager.getInstance()
.registerMapViewCreatedCallback(this.mapViewCreateCallback);
// 初始化路线搜索
const context = getContext(this);
this.routeSearch = new RouteSearch(context);
this.routeSearch.setRouteSearchListener(this.routeSearchListener);
}
aboutToDisappear(): void {
this.clearRouteLine();
MapViewManager.getInstance()
.unregisterMapViewCreatedCallback(this.mapViewCreateCallback);
if (this.mapView) {
this.mapView.onDestroy();
this.mapView = undefined;
this.aMap = undefined;
}
}
build() {
Column() {
// 标题栏
Row() {
Text('路线规划')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
}
.width('100%')
.height(50)
.padding({ left: 16 })
.backgroundColor('#673AB7')
// 路线类型选择
Row() {
ForEach(['drive', 'walk', 'ride'] as RouteType[], (type: RouteType) => {
Button(type === 'drive' ? '驾车' : type === 'walk' ? '步行' : '骑行')
.fontSize(13)
.height(36)
.layoutWeight(1)
.margin({ right: type !== 'ride' ? 8 : 0 })
.backgroundColor(this.routeType === type ? '#673AB7' : '#e0e0e0')
.fontColor(this.routeType === type ? Color.White : '#333')
.onClick(() => { this.routeType = type; })
})
Button('搜索')
.fontSize(13)
.height(36)
.width(70)
.margin({ left: 8 })
.enabled(!this.isSearching)
.onClick(() => this.searchRoute())
}
.width('100%')
.padding(12)
.backgroundColor('#f5f5f5')
// 地图区域
Stack() {
MapViewComponent({ mapViewName: MAP_VIEW_NAME })
.width('100%')
.height('100%')
// 路线信息
if (this.routeInfo) {
Column() {
Text(this.routeInfo)
.fontSize(12)
.fontColor('#333')
}
.padding(10)
.backgroundColor('rgba(255,255,255,0.95)')
.borderRadius(8)
.position({ x: 10, y: 10 })
}
// 操作提示
Text('长按地图设置终点')
.fontSize(11)
.fontColor('#fff')
.backgroundColor('rgba(0,0,0,0.6)')
.padding(6)
.borderRadius(4)
.position({ x: 10, y: 100 })
}
.width('100%')
.layoutWeight(1)
// 路线步骤
if (this.routeSteps.length > 0) {
Column() {
Text('路线详情')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.padding(8)
.width('100%')
.backgroundColor('#e0e0e0')
List() {
ForEach(this.routeSteps, (step: RouteStepInfo, index: number) => {
ListItem() {
Row() {
Text(`${index + 1}`)
.fontSize(12)
.fontColor(Color.White)
.width(24)
.height(24)
.textAlign(TextAlign.Center)
.backgroundColor('#673AB7')
.borderRadius(12)
Column() {
Text(step.instruction)
.fontSize(12)
.fontColor('#333')
.maxLines(2)
Text(`${this.formatDistance(step.distance)} | ${this.formatDuration(step.duration)}`)
.fontSize(10)
.fontColor('#999')
.margin({ top: 2 })
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
.margin({ left: 8 })
}
.width('100%')
.padding(8)
}
})
}
.height(120)
.divider({ strokeWidth: 1, color: '#eee' })
}
.backgroundColor(Color.White)
}
}
.width('100%')
.height('100%')
}
}
4. 驾车策略说明
// 驾车策略常量
RouteSearch.DrivingDefault // 默认(速度优先)
RouteSearch.DrivingNoHighway // 不走高速
RouteSearch.DrivingNoFare // 避免收费
RouteSearch.DrivingShortest // 距离最短
RouteSearch.DrivingHighway // 高速优先
RouteSearch.DrivingAvoidCongestion // 躲避拥堵
RouteSearch.DrivingMultiStrategy // 多策略
5. 设置途经点
// 添加途经点
const wayPoints: LatLonPoint[] = [
new LatLonPoint(39.95, 116.40),
new LatLonPoint(39.96, 116.42)
];
const query = new DriveRouteQuery(
fromAndTo,
RouteSearch.DrivingDefault,
wayPoints, // 途经点数组
undefined,
''
);
6. 设置避让区域
// 避让区域(矩形)
const avoidArea: LatLonPoint[] = [
new LatLonPoint(39.90, 116.38), // 左下角
new LatLonPoint(39.92, 116.40) // 右上角
];
const avoidPolygons: LatLonPoint[][] = [avoidArea];
const query = new DriveRouteQuery(
fromAndTo,
RouteSearch.DrivingDefault,
undefined,
avoidPolygons, // 避让区域
''
);
7. 路线绘制优化
7.1 使用路况颜色
// 根据路况设置不同颜色
private getTrafficColor(trafficStatus: number): number {
switch (trafficStatus) {
case 0: return 0xFF4CAF50; // 畅通-绿色
case 1: return 0xFFFFEB3B; // 缓行-黄色
case 2: return 0xFFFF9800; // 拥堵-橙色
case 3: return 0xFFF44336; // 严重拥堵-红色
default: return 0xFF2196F3; // 未知-蓝色
}
}
7.2 绘制带方向的路线
// 使用带箭头的纹理
options.setLineTexture(arrowTexture);
options.setUseTexture(true);
本篇小结
本篇教程我们学习了:
- ✅ 驾车路线规划实现
- ✅ 步行路线规划实现
- ✅ 骑行路线规划实现
- ✅ 路线绘制和视野调整
- ✅ 路线详情展示
- ✅ 途经点和避让区域设置
下一篇我们将学习绑图与测距功能。
班级
https://developer.huawei.com/consumer/cn/training/classDetail/fd34ff9286174e848d34cde7f512ce22?type=1%3Fha_source%3Dhmosclass&ha_sourceId=89000248
源码地址
https://gitcode.com/daleishen/gaodehmjiaocheng.git
更多推荐
所有评论(0)