HarmonyOS鸿蒙Next地图多信息窗实现
HarmonyOS鸿蒙Next地图多信息窗实现 目前HarmonyOSSDK中地图服务提供的信息窗能力只针对单marker,针对多marker场景目前没有规划,依赖地图服务的现有能力,可以不依赖地图服务的信息窗能力实现多信息窗。
export class InfoWindowOptions {
positionX:number = 0;
positionY:number = 0;
}
import { map, mapCommon, MapComponent } from '@kit.MapKit';
import { AsyncCallback, BusinessError } from '@kit.BasicServicesKit';
import { InfoWindowOptions } from './dto/InfoWindowOptions';
import { image } from '@kit.ImageKit';
@Entry
@Component
struct BasicMapDemo {
private TAG = "OHMapSDK_BasicMapDemo";
@State resultText: string = "result";
private mapOptions?: mapCommon.MapOptions;
private callback?: AsyncCallback<map.MapComponentController>;
private mapController?: map.MapComponentController;
@State infoWindowOptions: InfoWindowOptions = new InfoWindowOptions();
@State show: boolean = false;
private infoAnchorU: number = 0.5; // 信息窗X轴的偏移
private infoAnchorV: number = 0; // 信息窗Y轴的偏移
aboutToAppear(): void {
let target: mapCommon.LatLng = {
latitude: 31.984410259206815,
longitude: 118.76625379397866
}
let cameraPosition: mapCommon.CameraPosition = {
target: target,
zoom: 15
}
this.mapOptions = {
position: cameraPosition
}
this.callback = async (err, mapController) => {
if (!err) {
this.mapController = mapController;
try {
// 获取图片资源并转成 PixelMap
let mContext = getContext();
const fileData: Uint8Array = await mContext?.resourceManager?.getMediaContent($r('app.media.icon'));
let imageSource: image.ImageSource =
image.createImageSource(fileData.buffer.slice(0, fileData.buffer.byteLength));
let pixelMap: PixelMap = await imageSource.createPixelMap();
let markerOptions: mapCommon.MarkerOptions = {
position: {
latitude: 31.984410259206815,
longitude: 118.76625379397866
},
icon: pixelMap
}
const imageInfo: image.ImageInfo = await pixelMap.getImageInfo();
let marker = await this.mapController.addMarker(markerOptions);
let point: mapCommon.MapPoint = this.mapController.getProjection().toScreenLocation(marker.getPosition());
this.infoWindowOptions.positionX = point.positionX - imageInfo.size.width * (0.5 - this.infoAnchorU);
this.infoWindowOptions.positionY = point.positionY - imageInfo.size.height * (1 - this.infoAnchorV);
this.show = true;
this.mapController.on('cameraMove', () => {
if (this.mapController) {
let point: mapCommon.MapPoint = this.mapController.getProjection().toScreenLocation(marker.getPosition());
this.infoWindowOptions.positionX = point.positionX - imageInfo.size.width * (0.5 - this.infoAnchorU);
this.infoWindowOptions.positionY = point.positionY - imageInfo.size.height * (1 - this.infoAnchorV);
}
})
} catch (e) {
console.error('20250516 test error')
}
}
}
}
build() {
Stack() {
Column() {
MapComponent({ mapOptions: this.mapOptions, mapCallback: this.callback })
.width('100%')
.height('100%');
}.width('100%')
Column() {
Text('20250516 test')
.width(200)
.height(40)
.backgroundColor(Color.Green)
.textAlign(TextAlign.Center)
}.position(
{
x: px2vp(this.infoWindowOptions.positionX),
y: px2vp(this.infoWindowOptions.positionY)
})
.markAnchor( //设置信息窗在position的锚点,以信息窗左上角作为基准点进行偏移
{
x: '50%',
y: '100%'
}).visibility(this.show ? Visibility.Visible : Visibility.Hidden)
}.height('100%')
}
}
更多关于HarmonyOS鸿蒙Next地图多信息窗实现的实战教程也可以访问 https://www.itying.com/category-93-b0.html
开发者您好,如果想通过地图服务组件实现多信息窗效果,可以将需要展示在信息窗的信息放入自定义组件实现的marker图标中(参考自定义组件实现marker图标,在MarkerOptions参数的iconBuilder属性中添加自定义组件),然后创建多个marker标记即可。(多marker标记创建首先通过调用map.MapComponentController类的addMarker方法,该方法会返回添加的Marker实例;再通过不同的MarkerOptions参数调用该方法创建不同的marker实例。)如果以上方案无法满足开发者的诉求,请开发者提供详细的场景说明。
更多关于HarmonyOS鸿蒙Next地图多信息窗实现的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
鸿蒙Next地图多信息窗可通过Map组件的MapController实现。使用createInfoWindow方法创建信息窗,通过addInfoWindow添加到地图。可自定义信息窗内容与样式,支持点击事件。多个信息窗需管理各自ID与状态,调用showInfoWindow或hideInfoWindow控制显示。
目前HarmonyOS Next的地图服务确实只支持单个Marker的信息窗。要实现多信息窗,可以采用自定义UI叠加的方案,如你提供的代码所示。
核心思路是:
- 使用
Stack布局将地图组件与自定义信息窗组件叠加。 - 通过
getProjection().toScreenLocation()将地理坐标转换为屏幕坐标。 - 监听地图的
cameraMove事件,动态更新信息窗位置。 - 使用
position和markAnchor属性精确控制信息窗的显示位置。
你的实现方案是正确的,通过自定义Column或Row等容器组件作为信息窗,配合坐标转换和事件监听,可以灵活实现多个信息窗的显示与更新。这种方法不依赖地图服务的原生信息窗能力,完全通过UI组件实现,适用于多Marker场景。

