Docs / Basics / Markers

Markers

A marker is one state object placed inside the map view. Rendering is handled by the SDK internal engine, which switches technique by count: up to 2,000 markers it uses each map SDK native markers by default and draws raster tiles beyond that — a threshold you can change by passing markerTilingOptions to the map view.

ANDROID
com.mapconductor:core
iOS
MapConductorCore
REACT
@mapconductor/js-sdk-react
Platform

01 · Marker state

MarkerState represents a single marker — position, icon, events and any payload. Assigning to a property applies immediately, and there is no per-provider type.

MarkerState · Jetpack Compose
val marker =
    MarkerState(
        position = GeoPoint.fromLatLong(21.3069, -157.8583),
        icon = DefaultMarkerIcon(fillColor = Color.Red, label = "A"),
        extra = postOffice,
        onClick = { clicked -> viewModel.onMarkerClick(clicked) },
    )

// Assigning to a property is all it takes to redraw
marker.position = nextPoint
Property
Description
position
Latitude and longitude; assign to move the marker.
icon
The icon. Falls back to the default pin.
extra
Arbitrary payload, handed back on click for info bubbles and the like.
clickable / draggable
Whether the marker is tappable and draggable.
zIndex
Stacking order; unset (null) per marker by default on all three platforms, in which case markers stack by latitude. The marker layer itself sits at 10.
onClick / onDrag…
Handlers for tap, drag and animation start/end.

02 · Icons

From a coloured, labelled default pin to images, canvases and bubble-shaped icons. Every icon looks the same across providers.

ColorDefaultIcon

The standard pin with fill, stroke, label and scale. Called DefaultMarkerIcon on iOS; on Android DefaultMarkerIcon is an alias of ColorDefaultIcon.

ImageIcon / ImageDefaultIcon

Use an image or bitmap directly, with a custom anchor. Android additionally has DrawableDefaultIcon, which takes a Drawable straight.

CircleIcon / FlagIcon

Simple circle and flag shapes from the icons package.

RoundInfoBubbleIcon

Icon plus label inside a round bubble — good for prices.

RightTailInfoBubbleIcon

Right-tailed bubble with a label and a second line.

scale · anchor · debug

Scale, anchor and a debug overlay for hit areas are common to all icons.

03 · The internal rendering engine

Drawing is delegated to the SDK internal rendering engine. While the count is low it uses each map SDK native markers, keeping native hit testing and animation.

Past 2,000 markers the engine changes technique: it renders the markers into tile images and overlays them as a raster layer, removing the per-marker add/update cost in the native SDK. Your code does not change.

Figure · the technique switches with the marker count
≤ 2,000

Native markers

One native marker per state. Tap, drag and animation behave exactly as the platform does.
2,000+
> 2,000

Raster tiles

Markers are drawn into tiles and overlaid as a raster layer. With no per-marker updates, camera work stays smooth at tens of thousands.
The switch is automatic. The threshold defaults to 2,000: pass the options to the map view (markerTiling on Android, markerTilingOptions on iOS and React) to change minMarkerCount, and the same options carry the tile cache and per-zoom icon scale. Disabled keeps native markers at any count.
Sample video · Marker tile rendering
Sample · all 24,526 markers on screen at once
minMarkerCount
2000 · configurable
cacheSize
8 MB
enabled
true
debugTileOverlay
false
PostOfficeViewModel.kt · 24,526 markers
// On by default; pass it to the map view to change the threshold
// (the Android parameter is called markerTiling)
val markerTiling =
    MarkerTilingOptions.Default.copy(
        minMarkerCount = 500, // switch to tile rendering from 500 markers
        iconScaleCallback = { _, zoom ->
            if (zoom > 10) 0.8 else if (zoom > 5) 0.5 else 0.2
        },
    )

GoogleMapView(state = mapViewState, markerTiling = markerTiling) { /* markers */ }

// Disable it to keep native markers at any count
val plain = MarkerTilingOptions.Disabled
SPATIAL INDEX

A spatial index for lookups

With large marker sets a hex-cell spatial index answers viewport queries and hit tests without scaling in the number of markers. For small sets a brute-force scan is faster, so that is used instead.

CLUSTERING

Clustering is a separate module

Grouping nearby markers into one badge — "markers at scale" — is an add-on module. The tile rendering described here is built in and works independently of clustering.

04 · Animation

A small set of animations ships with the SDK. Set one at creation or call animate() later; start and end are reported through handlers.

MarkerAnimation.Drop

Drops in from above and lands — good for revealing search results.

MarkerAnimation.Bounce

Bounces in place — good for highlighting a selection.
AnimationPageViewModel.kt
// Set one at creation, or call animate() later
MarkerState(position = point, animation = MarkerAnimation.Bounce)

override fun onMarkerClick(clicked: MarkerState) {
    clicked.animate(clicked.extra as? MarkerAnimation)
}

Animating markers are drawn on a dedicated overlay, so they animate even while tile rendering is active. Durations are configurable in the SDK settings.

Related pages