鸿蒙 地图开发:标记(Marker)增加
开发中,标记(Marker)是最常用的功能之一。点标记用来在地图上标记任何位置,例如用户位置、车辆位置、店铺位置等一切带有位置属性的事物。
本文介绍如下:
标记的基本使用:添加标记、修改属性
自定义标记:自定义图标
标记文字控制:文字显隐、文字内容
事件监听:点击、拖拽、长按事件
标记动画:旋转、缩放、平移、透明、图片动画播放
一、标记
Map Kit提供的点标记功能(Marker)封装了大量的触发事件:点击事件、长按事件、拖拽事件。
版本说明
| 版本 | 新增功能 |
|---|---|
| 5.1.1(19) | 支持控制Marker文字显隐功能 |
| 6.0.0(20) | 支持自定义组件实现Marker图标功能 |
| 6.1.1(24) | 支持监听Marker长按事件 |
二、核心接口
| 接口 | 描述 |
|---|---|
MarkerOptions | 标记参数 |
addMarker(options) | 在地图上添加标记 |
Marker | 标记,支持更新和查询相关属性 |
三、开发步骤
3.1 导入模块
import { MapComponent, mapCommon, map } from '@kit.MapKit'; import { AsyncCallback } from '@kit.BasicServicesKit';3.2 添加标记
@Entry @Component struct MarkerDemo { private mapOptions?: mapCommon.MapOptions; private mapController?: map.MapComponentController; private marker?: map.Marker; aboutToAppear(): void { this.mapOptions = { position: { target: { latitude: 31.984410259206815, longitude: 118.76625379397866 }, zoom: 15 } }; this.callback = async (err, mapController) => { if (!err) { this.mapController = mapController; let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 31.984410259206815, longitude: 118.76625379397866 }, rotation: 0, visible: true, zIndex: 0, alpha: 1, anchorU: 0.5, anchorV: 1, clickable: true, draggable: true, flat: false }; this.marker = await this.mapController.addMarker(markerOptions); } }; } build() { Stack() { MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback }) }.height('100%') } }3.3 MarkerOptions参数
| 参数 | 类型 | 说明 |
|---|---|---|
position | LatLng | 标记位置(纬度、经度) |
rotation | number | 旋转角度 |
visible | boolean | 是否可见 |
zIndex | number | 层级 |
alpha | number | 透明度 |
anchorU | number | 锚点U坐标 |
anchorV | number | 锚点V坐标 |
clickable | boolean | 是否可点击 |
draggable | boolean | 是否可拖拽 |
flat | boolean | 是否平贴地图 |
icon | string | 自定义图标(rawfile相对路径) |
annotations | Array | 文字标注配置 |
collisionRule | CollisionRule | 碰撞规则 |
title | string | 信息窗标题 |
snippet | string | 信息窗子标题 |
3.4 修改标记属性
// 设置标记可拖拽 this.marker.setDraggable(true); // 设置标记锚点 this.marker.setMarkerAnchor(1.0, 1.0);四、自定义标记
在MarkerOptions中将icon属性设置为自定义图标的资源。
let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 31.984410259206815, longitude: 118.76625379397866 }, icon: 'test.png' // 图标存放在resources/rawfile }; this.marker = await this.mapController.addMarker(markerOptions);五、控制Marker文字显隐
let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 31.984410259206815, longitude: 118.76625379397866 }, annotations: [{ content: "text", // 定义标题内容 fontStyle: 1, strokeWidth: 3, fontSize: 15 }] }; this.marker = await this.mapController.addMarker(markerOptions); // 设置文字隐藏 this.marker.setAnnotationVisible(false); // 查询当前显隐状态 let isAnnotationVisible = this.marker.isAnnotationVisible();六、碰撞检测
通过设置collisionRule属性,可以设置标记的冲突处理规则。
let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 31.984410259206815, longitude: 118.76625379397866 }, icon: 'icon.png', annotations: [{ content: "Test", fontStyle: 1, strokeWidth: 3, fontSize: 15 }], // 设置碰撞规则为图标和名称都参与碰撞 collisionRule: mapCommon.CollisionRule.ALL, annotationPosition: mapCommon.TextPosition.TOP };七、事件监听
7.1 标记点击事件
let callback = (marker: map.Marker) => { console.info(`markerClick: ${marker.getId()}`); }; this.mapEventManager.on("markerClick", callback);7.2 标记拖拽事件
需要先设置标记可拖拽,然后监听拖拽事件。
// 设置标记可拖拽 this.marker.setDraggable(true); // 监听标记开始拖拽 this.mapEventManager.on("markerDragStart", (marker: map.Marker) => { console.info(`markerDragStart: ${marker.getId()}`); }); // 监听标记拖拽过程 this.mapEventManager.on("markerDrag", (marker: map.Marker) => { console.info(`markerDrag: ${marker.getId()}`); }); // 监听标记拖拽结束 this.mapEventManager.on("markerDragEnd", (marker: map.Marker) => { console.info(`markerDragEnd: ${marker.getId()}`); });7.3 标记长按事件(6.1.1+)
let callback = (markerLong: map.Marker) => { console.info(`markerLongClick: ${markerLong.getId()}`); }; this.mapEventManager.onMarkerLongClick(callback);八、信息窗
8.1 基础信息窗
let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 31.984410259206815, longitude: 118.76625379397866 } }; this.marker = await this.mapController?.addMarker(markerOptions); // 设置信息窗的标题和子标题 this.marker.setTitle('南京'); this.marker.setSnippet('华东地区'); // 设置标记可点击 this.marker.setClickable(true); // 设置信息窗的锚点位置 this.marker.setInfoWindowAnchor(1, 1); // 设置信息窗可见(点击标记后可展示) this.marker.setInfoWindowVisible(true);8.2 自定义信息窗
@Entry @Component struct MarkerDemo { private mapOptions?: mapCommon.MapOptions; private mapController?: map.MapComponentController; aboutToAppear(): void { this.mapOptions = { position: { target: { latitude: 32.120750, longitude: 118.788765 }, zoom: 15 } }; this.callback = async (err, mapController) => { if (!err) { this.mapController = mapController; let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 32.120750, longitude: 118.788765 }, clickable: true, title: "自定义信息窗" }; await this.mapController?.addMarker(markerOptions); } }; } @BuilderParam customInfoWindow: ($$: map.MarkerDelegate) => void = this.customInfoWindowBuilder; @Builder customInfoWindowBuilder($$: map.MarkerDelegate) { if ($$.marker) { Text($$.marker.getTitle()) .width("50%") .height(50) .backgroundColor(Color.Green) .textAlign(TextAlign.Center) .fontColor(Color.Black) } } build() { MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback, customInfoWindow: this.customInfoWindow }) } }九、标记动画
9.1 动画类型
| 动画类 | 说明 |
|---|---|
AlphaAnimation | 控制透明度的动画 |
RotateAnimation | 控制旋转的动画 |
ScaleAnimation | 控制缩放的动画 |
TranslateAnimation | 控制平移的动画 |
PlayImageAnimation | 控制多张图片的动画 |
AnimationSet | 动画集合 |
9.2 旋转动画示例
let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 32.020750, longitude: 118.788765 } }; let marker: map.Marker = await mapController.addMarker(markerOptions); // 构造RotateAnimation对象(0度到270度) let animation = new map.RotateAnimation(0, 270); animation.setDuration(2000); // 动画执行时间 animation.setFillMode(map.AnimationFillMode.BACKWARDS); // 动画结束状态 animation.setRepeatMode(map.AnimationRepeatMode.REVERSE); // 重复模式 animation.setRepeatCount(100); // 重复次数 // 设置动画开始/结束监听 animation.on("animationStart", () => console.info("动画开始")); animation.on("animationEnd", () => console.info("动画结束")); // 设置动画并启动 marker.setAnimation(animation); marker.startAnimation();9.3 图片动画播放
let images: Array<ResourceStr | image.PixelMap> = [ 'icon/avocado.png', // rawfile目录 'icon/20231027.png', $r('app.media.maps_blue_dot') // base/media目录 ]; let animation: map.PlayImageAnimation = new map.PlayImageAnimation(); await animation.addImages(images); animation.setDuration(3000); animation.setFillMode(map.AnimationFillMode.BACKWARDS); animation.setRepeatMode(map.AnimationRepeatMode.REVERSE); animation.setRepeatCount(100); marker.setAnimation(animation); marker.startAnimation();十、自定义组件实现Marker图标(6.0.0+)
@Entry @Component struct MarkerDemo { aboutToAppear(): void { this.callback = async (err, mapController) => { if (!err) { let markerOptions: mapCommon.MarkerOptions = { position: { latitude: 32.120750, longitude: 118.788765 }, iconBuilder: () => { this.renderBuilder(); } // 自定义组件 }; this.marker = await this.mapController?.addMarker(markerOptions); } }; } @Builder renderBuilder() { Stack({ alignContent: Alignment.Center }) { Image($r('app.media.iconbuilder')).syncLoad(true) } .height(50) .width(50) } }