DEV Community

HarmonyOS
HarmonyOS

Posted on

Add Multiple Markers with Custom Styles on HarmonyOS Map

Read the original article:Add Multiple Markers with Custom Styles on HarmonyOS Map

Add Multiple Markers with Custom Styles on HarmonyOS Map

Requirement Description

In a map-based application, developers may need to add multiple markers (e.g., user location, vehicle, store) where each marker has a different custom style instead of the default system-provided icons.

Background Knowledge

  • Marker is a core feature in Map Kit that supports events such as tap, long press, and drag.
  • By default, the system provides a standard marker style, but developers can override it:
    • Use icon property of MarkerOptions to set custom images.
    • Use componentSnapshot with a custom @Builder component to generate pixel maps and apply them to markers.
  • Markers can be added and managed via MapComponentController.addMarker().

Implementation Steps

Step 1: Define a custom marker style

Use @Builder to build a styled UI component, which will later be converted into an image for the marker.

@Builder
RandomBuilder() {
  Row() {
    Image($r('app.media.startIcon')).width(18).height(24)
    Column() {
      Text("200m")
        .fontSize(12)
        .fontColor("#1f2642")
        .fontWeight(FontWeight.Bold)
      Text("35 mins")
        .fontSize(12)
        .fontColor("#1f2642")
        .fontWeight(FontWeight.Bold)
        .margin({ top: 1 })
    }
    .margin({ left: 6 })
    .alignItems(HorizontalAlign.Start)

    Divider()
      .vertical(true)
      .width(1)
      .height(18)
      .backgroundColor("#c1cadd")
      .margin({ left: 8, right: 8 })

    Image($r('app.media.startIcon')).width(18).height(18)

    Text("Navigate")
      .fontSize(12)
      .fontColor("#1f2642")
      .fontWeight(FontWeight.Bold)
      .margin({ left: 2 })
      .onClick(() => {
        // handle navigation click
      })
  }
  .margin({ bottom: 3 })
  .padding({ left: 6, right: 6, top: 8, bottom: 8 })
  .backgroundColor(Color.White)
  .borderRadius(12)
  .shadow({ radius: 12, color: "#33000000" })
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Convert Builder to PixelMap and add Marker

Use componentSnapshot.createFromBuilder() to generate an image from the custom Builder and pass it as icon in MarkerOptions.

addMarker() {
  componentSnapshot.createFromBuilder(() => { this.RandomBuilder() },
    async (error: Error, pixmap: image.PixelMap) => {
      if (error) {
        console.error("error: " + JSON.stringify(error))
        return;
      }

      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,
        icon: pixmap
      };
      this.mapController?.addMarker(markerOptions);
    })
}
Enter fullscreen mode Exit fullscreen mode

By calling addMarker() multiple times with different MarkerOptions and different custom Builders, you can render multiple markers with unique styles.

Test Results

  • Multiple markers displayed correctly at specified coordinates.
  • Each marker reflected its custom style (icon, text, background).
  • Markers responded to tap/drag as expected.

Limitations or Considerations

  • Remote icons are not supported directly in icon. Only string, image.PixelMap, or Resource types are allowed.
    • Workaround: Download remote image locally, then use local relative path or Base64 (data:image/png;base64,...).
  • Markers consume memory; avoid using too many high-resolution icons.
  • Use remove() to delete a specific marker, or clear() to remove all markers.

Written by Arif Emre Ankara

Top comments (0)