华为HarmonyOS地图服务 7- 在地图上绘制标记

场景介绍

本章节将向您介绍如何在地图的指定位置添加标记以标识位置、商家、建筑等。

点标记用来在地图上标记任何位置,例如用户位置、车辆位置、店铺位置等一切带有位置属性的事物。Map Kit提供的点标记功能(又称 Marker)封装了大量的触发事件,例如点击事件、长按事件、拖拽事件。

Marker有默认风格,同时也支持自定义。由于内容丰富,以下只能展示一些基础功能的使用,详细内容可参见接口文档

接口说明

添加标记功能主要由MarkerOptionsaddMarkerMarker提供,更多接口及使用方法请参见接口文档

接口名 描述
MarkerOptions Marker相关属性。
addMarker(options: mapCommon.MarkerOptions): Promise<Marker> 在地图上添加标记。
Marker 标记,支持更新和查询标记。

开发步骤

添加标记

  1. 导入相关模块。

    TypeScript 复制代码
    import { MapComponent, mapCommon, map } from '@kit.MapKit';
    import { AsyncCallback } from '@kit.BasicServicesKit';
  2. 添加标记,在Callback方法中创建初始化参数并新建Marker

    TypeScript 复制代码
    @Entry
    @Component
    struct MarkerDemo {
    private mapOptions?: mapCommon.MapOptions;
    private mapController?: map.MapComponentController;
    private callback?: AsyncCallback<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;
    // Marker初始化参数
    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
    };
    // 创建Marker
    this.marker = await this.mapController.addMarker(markerOptions);
    }
    };
    }
    build() {
    Stack() {
    Column() {
    MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback });
    }.width('100%')
    }.height('100%')
    }
    }
  3. 在添加标记之后,修改已经设置的标记属性。

    TypeScript 复制代码
    // 设置标记可拖拽
    this.marker.setDraggable(true);
    // 设置标记锚点
    this.marker.setMarkerAnchor(1.0, 1.0);

自定义标记

通过在MarkerOptions中将icon属性设置为自定义图标的资源,可将默认标记图标修改成自定义图标。

TypeScript 复制代码
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,
// 图标存放在resources/rawfile,icon参数传入rawfile文件夹下的相对路径
icon: 'test.png'
};
this.marker = await this.mapController.addMarker(markerOptions);

设置监听标记点击事件

TypeScript 复制代码
this.mapController.on("markerClick", (marker) => {
console.info(`on-markerClick marker = ${marker.getId()}`);
});

设置监听标记拖动事件

Marker的拖拽属性设置为true,然后调用on(type: 'markerDragStart' , callback: Callback<Marker>)方法监听标记是否开始拖拽。

调用on(type: 'markerDrag' , callback: Callback<Marker>),监听标记拖动过程。

调用on(type: 'markerDragEnd' , callback: Callback<Marker>),监听标记拖动结束事件。

TypeScript 复制代码
// 设置标记可拖拽
this.marker.setDraggable(true);
// 监听标记开始拖拽
this.mapController.on("markerDragStart", (marker) => {
console.info(`on-markerDragStart marker = ${marker.getId()}`);
});
// 监听标记拖拽事件
this.mapController.on("markerDrag", (marker) => {
console.info(`on-markerDrag marker = ${marker.getId()}`);
});
// 监听标记拖拽结束
this.mapController.on("markerDragEnd", (marker) => {
console.info(`on-markerDragEnd marker = ${marker.getId()}`);
});

信息窗

TypeScript 复制代码
// 添加信息窗
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);

自定义信息窗

TypeScript 复制代码
import { map, mapCommon, MapComponent } from '@kit.MapKit'
import { AsyncCallback } from '@kit.BasicServicesKit'
@Entry
@Component
struct MarkerDemo {
private TAG = "OHMapSDK_MarkerDemo";
private mapOption?: mapCommon.MapOptions;
private mapController?: map.MapComponentController;
private callback?: AsyncCallback<map.MapComponentController>;
aboutToAppear(): void {
this.mapOption = {
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);
}
}
}
build() {
Stack() {
Column() {
MapComponent({
mapOptions: this.mapOption,
mapCallback: this.callback,
// 自定义信息窗
customInfoWindow: this.customInfoWindow
})
.width('100%')
.height('100%');
}.width('100%')
}.height('100%')
}
// 自定义信息窗BuilderParam
@BuilderParam customInfoWindow: ($$: map.MarkerDelegate) => void = this.customInfoWindowBuilder;
// 自定义信息窗Builder
@Builder
customInfoWindowBuilder($$: map.MarkerDelegate) {
if ($$.marker) {
Text($$.marker.getTitle())
.width("50%")
.height(50)
.backgroundColor(Color.Green)
.textAlign(TextAlign.Center)
.fontColor(Color.Black)
.font({ size: 25, weight: 10, style: FontStyle.Italic })
.border({ width: 3, color: Color.Black, radius: 25, style: BorderStyle.Dashed })
}
}
}

标记动画

Marker支持设置旋转、缩放、平移、透明、图片动画播放和组合动画效果。

接口名 描述
AlphaAnimation 控制透明度的动画类。
RotateAnimation 控制旋转的动画类。
ScaleAnimation 控制缩放的动画类。
TranslateAnimation 控制平移的动画类。
PlayImageAnimation 控制多张图片的动画类。
AnimationSet 动画集合。

旋转动画效果的示例代码如下:

TypeScript 复制代码
import { map, mapCommon, MapComponent } from '@kit.MapKit';
import { AsyncCallback } from '@kit.BasicServicesKit';
@Entry
@Component
struct MarkerDemo {
private mapOption?: mapCommon.MapOptions;
private callback?: AsyncCallback<map.MapComponentController>;
aboutToAppear(): void {
this.mapOption = {
position: {
target: {
latitude: 32.020750,
longitude: 118.788765
},
zoom: 11
}
}
this.callback = async (err, mapController) => {
if (!err) {
// 构造MarkerOptions对象
let markerOptions: mapCommon.MarkerOptions = {
position: {
latitude: 32.020750,
longitude: 118.788765
},
};
// 新建marker
let marker: map.Marker = await mapController.addMarker(markerOptions);
// 构造RotateAnimation对象
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("start", () => {
console.info('start RotateAnimation');
})
animation.on("end", () => {
console.info('end RotateAnimation');
})
// 设置动画
marker.setAnimation(animation);
// 开启动画
marker.startAnimation();
}
}
}
build() {
Stack() {
Column() {
MapComponent({ mapOptions: this.mapOption, mapCallback: this.callback })
}.width('100%')
}.height('100%')
}
}

展示效果如图:

图片动画播放

TypeScript 复制代码
import { map, mapCommon, MapComponent } from '@kit.MapKit';
import { AsyncCallback } from '@kit.BasicServicesKit';
import { image } from '@kit.ImageKit';
@Entry
@Component
struct MarkerDemo {
private mapOption?: mapCommon.MapOptions;
private callback?: AsyncCallback<map.MapComponentController>;
aboutToAppear(): void {
this.mapOption = {
position: {
target: {
latitude: 32.020750,
longitude: 118.788765
},
zoom: 11
}
}
this.callback = async (err, mapController) => {
if (!err) {
// 构造MarkerOptions对象
let markerOptions: mapCommon.MarkerOptions = {
position: {
latitude: 32.020750,
longitude: 118.788765
},
};
let mContext = getContext();
const fileData: Uint8Array = await mContext?.resourceManager?.getRawFileContent('icon/icon.png');
let imageSource: image.ImageSource = image.createImageSource(fileData.buffer.slice(0, fileData.buffer.byteLength));
let pixelMap: PixelMap = await imageSource.createPixelMap();
let images: Array<ResourceStr | image.PixelMap> = [
// 图标需存放在resources/rawfile
'icon/avocado.png',
'icon/20231027.png',
pixelMap,
$r('app.media.maps_blue_dot')
]
// 新建marker
let marker: map.Marker = await mapController.addMarker(markerOptions);
// 构造RotateAnimation对象
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);
// 根据开发需要设置动画监听
animation.on("start", () => {
console.info('start RotateAnimation');
})
animation.on("end", () => {
console.info('end RotateAnimation');
})
// 设置动画
marker.setAnimation(animation);
// 开启动画
marker.startAnimation();
}
}
}
build() {
Stack() {
Column() {
MapComponent({ mapOptions: this.mapOption, mapCallback: this.callback })
}.width('100%')
}.height('100%')
}
}

展示效果如图:

相关推荐
OH五星上将37 分钟前
OpenHarmony(鸿蒙南向开发)——标准系统方案之瑞芯微RK3566移植案例(上)
stm32·嵌入式硬件·harmonyos·openharmony·鸿蒙开发·系统移植
让开,我要吃人了3 小时前
HarmonyOS鸿蒙开发实战(5.0)自定义全局弹窗实践
前端·华为·移动开发·harmonyos·鸿蒙·鸿蒙系统·鸿蒙开发
Lisce9603104 小时前
利士策分享,华为三折叠手机:重塑未来科技生活的里程碑
科技·华为·智能手机
云兮Coder4 小时前
鸿蒙Harmony应用开发,数据驾驶舱页面的实现
华为·harmonyos
千千小屋grow5 小时前
[已更新]2024数学建模研赛华为杯E题详细思路代码成品文章研究生数学建模数模辅导
数学建模·华为
繁依Fanyi5 小时前
828华为云征文|华为Flexus云服务器打造《我的世界》游戏服务器
java·服务器·开发语言·python·算法·华为·华为云
kirk_wang8 小时前
鸿蒙开发(HarmonyOS)组件化浅谈
华为·harmonyos
繁依Fanyi8 小时前
828 华为云征文|华为 Flexus 云服务器打造 Laverna 在线笔记应用
运维·服务器·笔记·python·算法·华为·华为云
安防视频中间件/视频资源汇聚平台9 小时前
华为摄像机/NVR主动注册协议接入SVMSP平台
华为·信息可视化·实时音视频·视频编解码·svmspro