鸿蒙原生开发手记:徒步迹 - 自定义地图标记与气泡弹窗
·

鸿蒙原生开发手记:徒步迹 - 自定义地图标记与气泡弹窗
打造个性化地图交互,提升用户体验
一、前言
默认的地图标记样式单一,不能满足 App 的品牌需求。本文介绍如何实现自定义地图标记图标和气泡弹窗(InfoWindow),让地图交互更丰富。
二、自定义标记图标
2.1 使用自定义图片
function addCustomMarker(map: MapView): void {
map.addMarker({
position: { lat: 39.908, lng: 116.397 },
title: '徒步起点',
icon: 'custom_marker_start', // resources/base/media 中的图片
anchorPoint: { x: 0.5, y: 1 }, // 锚点(底部居中)
zIndex: 10, // 层级
alpha: 1.0, // 透明度
draggable: false, // 是否可拖拽
});
}
2.2 不同状态的标记样式
enum MarkerType {
START, // 起点(绿色)
WAYPOINT, // 途经点(蓝色)
END, // 终点(红色)
CURRENT, // 当前位置(脉冲动画)
}
function getMarkerIcon(type: MarkerType): string {
switch (type) {
case MarkerType.START:
return 'marker_start';
case MarkerType.WAYPOINT:
return 'marker_waypoint';
case MarkerType.END:
return 'marker_end';
case MarkerType.CURRENT:
return 'marker_current';
}
}
// 批量添加路线标记
function addRouteMarkers(map: MapView, waypoints: Waypoint[]): void {
waypoints.forEach((wp, index) => {
let type: MarkerType;
if (index === 0) type = MarkerType.START;
else if (index === waypoints.length - 1) type = MarkerType.END;
else type = MarkerType.WAYPOINT;
map.addMarker({
position: { lat: wp.latitude, lng: wp.longitude },
title: wp.name,
icon: getMarkerIcon(type),
});
});
}
三、气泡弹窗(InfoWindow)
3.1 基础弹窗
function showInfoWindow(map: MapView, marker: Marker): void {
marker.showInfoWindow({
title: '香山徒步起点',
snippet: '海拔 120m · 距市区 20km',
// 点击弹窗事件
onClick: () => {
console.log('弹窗被点击');
// 跳转到路线详情页
router.pushUrl({ url: 'pages/RouteDetailPage' });
},
});
}
3.2 自定义信息窗
// 使用自定义组件作为信息窗
@Component
struct CustomInfoWindow {
@Prop routeName: string = '';
@Prop distance: string = '';
@Prop elevation: string = '';
@Prop difficulty: string = '';
build() {
Column() {
Text(this.routeName)
.fontSize(14)
.fontWeight(FontWeight.Bold);
Row() {
Text(`距离: ${this.distance}`).fontSize(12).fontColor('#666');
Text(`爬升: ${this.elevation}`).fontSize(12).fontColor('#666').margin({ left: 8 });
}
.margin({ top: 4 });
Text(`难度: ${this.difficulty}`)
.fontSize(12)
.fontColor('#4CAF50')
.margin({ top: 2 });
}
.padding(10)
.backgroundColor(Color.White)
.borderRadius(8);
}
}
// 在标记点击时显示自定义弹窗
map.onMarkerClick((marker: Marker) => {
// 使用自定义布局
marker.showInfoWindow({
customView: {
component: CustomInfoWindow({
routeName: '香山徒步',
distance: '8.5km',
elevation: '320m',
difficulty: '中等',
}),
width: 200,
height: 120,
},
});
});
四、标记聚合
当地图上有大量标记时,可以使用标记聚合功能:
function enableMarkerClustering(map: MapView): void {
// 启用聚合
map.setMarkerClustering(true);
// 设置聚合样式
map.setClusterOptions({
icon: 'cluster_icon',
textColor: Color.White,
textSize: 14,
clusterRange: 60, // 聚合距离(px)
});
}
五、动画与交互
5.1 标记动画
// 标记点击时的弹跳动画
function animateMarkerBounce(marker: Marker): void {
animateTo({ duration: 300, curve: Curve.SpringMotion }, () => {
marker.setAlpha(0.5); // 闪烁
});
setTimeout(() => {
animateTo({ duration: 300 }, () => {
marker.setAlpha(1.0);
});
}, 300);
}
5.2 地图区域搜索
async function searchNearbyRoutes(
map: MapView,
center: { lat: number; lng: number },
radius: number
): Promise<void> {
// 显示搜索范围圈
map.addCircle({
center: center,
radius: radius,
fillColor: 'rgba(76, 175, 80, 0.1)',
strokeColor: '#4CAF50',
strokeWidth: 2,
});
// 搜索附近的路线并添加标记
const routes = await apiService.getRoutesByLocation(center.lat, center.lng, radius);
for (let route of routes) {
map.addMarker({
position: { lat: route.latitude, lng: route.longitude },
title: route.name,
icon: 'route_marker',
});
}
}
六、实战:徒步迹路线详情地图
@Component
struct RouteMapView {
@Prop routeId: number = 0;
private mapView!: MapView;
aboutToAppear(): void {
// 页面加载后初始化地图
}
build() {
Column() {
MapComponent({
mapOptions: {
center: { lat: 39.908, lng: 116.397 },
zoom: 13,
},
onMapReady: (map: MapView) => {
this.mapView = map;
this.loadRouteData();
},
})
.width('100%')
.height(300);
Row() {
Text('香山徒步').fontSize(16).fontWeight(FontWeight.Bold);
Text('8.5km · 中等').fontSize(13).fontColor('#666').margin({ left: 8 });
}
.width('100%')
.padding(12);
}
}
loadRouteData(): void {
// 绘制路线
const points = [
{ lat: 39.908, lng: 116.397 },
{ lat: 39.912, lng: 116.400 },
{ lat: 39.915, lng: 116.405 },
{ lat: 39.918, lng: 116.402 },
];
this.mapView.addPolyline({
path: points,
strokeWidth: 5,
strokeColor: '#4CAF50',
});
// 添加起终点标记
this.mapView.addMarker({
position: points[0],
title: '起点', icon: 'marker_start',
});
this.mapView.addMarker({
position: points[points.length - 1],
title: '终点', icon: 'marker_end',
});
}
}
七、总结
自定义标记和弹窗是提升地图交互体验的重要手段。通过自定义图标、气泡弹窗和标记聚合,可以让“徒步迹“的地图展示更加个性化和实用。
下一篇文章将开发天气卡片组件。
下一篇预告:鸿蒙原生开发手记:徒步迹 - 天气卡片组件开发
更多推荐



所有评论(0)