Skip to content

Overlays API

Overlay components must be rendered as children of MapView. They let you draw points, lines, polygons, circles, heatmaps, massive point sets, and clusters.

⚠️ Overlays depend on the map instance. Make sure privacy compliance is completed on fresh install before rendering MapView. After consent is granted once, native code restores it automatically on later cold starts.

Coordinate formats

All overlay coordinates support:

  • object form: { latitude, longitude }
  • array form: [longitude, latitude]

Marker

Props

PropertyTypeDefaultDescription
positionLatLngPoint-Marker coordinate, required
iconstring | ImageSourcePropType-Custom icon
iconWidthnumber40Icon width, only used with icon
iconHeightnumber40Icon height, only used with icon
titlestring-Title
snippetstring-Subtitle / description
opacitynumber-Opacity between 0 ~ 1, Android only
draggablebooleanfalseWhether the marker is draggable
flatbooleanfalseLay marker flat on the map, Android only
zIndexnumber-Z index, Android only
anchorPoint-Anchor ratio, Android only
centerOffsetPoint-View offset, iOS only
animatesDropbooleanfalseDrop animation, iOS only
pinColor'red' | 'orange' | 'yellow' | 'green' | 'cyan' | 'blue' | 'violet' | 'magenta' | 'rose' | 'purple'-Default pin color
childrenReact.ReactNode-Custom marker content, measured automatically from layout
cacheKeystring-Cache key for custom marker rendering
growAnimationbooleanfalseGrow animation on Android / iOS
smoothMovePathLatLng[]-Path for smooth movement
smoothMoveDurationnumber10Total movement duration in seconds

Events

EventParametersDescription
onMarkerPressNativeSyntheticEvent<LatLng>Marker tap
onMarkerDragStartNativeSyntheticEvent<LatLng>Drag start
onMarkerDragNativeSyntheticEvent<LatLng>Dragging
onMarkerDragEndNativeSyntheticEvent<LatLng>Drag end

Example

tsx
<MapView style={{ flex: 1 }}>
  <Marker
    position={{ latitude: 39.9, longitude: 116.4 }}
    title="Beijing"
    snippet="Capital of China"
    draggable
    onMarkerPress={(e) => console.log('Marker pressed', e.nativeEvent)}
    onMarkerDragEnd={(e) => console.log('Drag end', e.nativeEvent)}
  />
</MapView>

Custom view

tsx
<Marker
  position={{ latitude: 39.9, longitude: 116.4 }}
  cacheKey="custom-marker-1"
>
  <View style={{ backgroundColor: '#fff', padding: 8, borderRadius: 8 }}>
    <Text>Custom Content</Text>
  </View>
</Marker>

Smooth movement

tsx
<Marker
  position={{ latitude: 39.9, longitude: 116.4 }}
  smoothMovePath={[
    { latitude: 39.91, longitude: 116.41 },
    { latitude: 39.92, longitude: 116.42 },
    { latitude: 39.93, longitude: 116.43 },
  ]}
  smoothMoveDuration={5}
/>

Polyline

Props

PropertyTypeDefaultDescription
pointsLatLngPoint[]-Polyline coordinates, required
strokeWidthnumber-Line width
strokeColorColorValue-Line color
zIndexnumber-Z index
colorsColorValue[]-Segment colors
gradientbooleanfalseGradient line, Android only
geodesicbooleanfalseGeodesic line, Android only
simplificationTolerancenumber-Path simplification tolerance in meters
dottedbooleanfalseDotted line, Android only
texturestring-Texture image

Events

EventParametersDescription
onPolylinePressNativeSyntheticEvent<{}>Polyline tap

Example

tsx
<Polyline
  points={[
    { latitude: 39.9, longitude: 116.4 },
    { latitude: 39.95, longitude: 116.45 },
    { latitude: 40.0, longitude: 116.5 },
  ]}
  strokeWidth={5}
  strokeColor="#FF1677FF"
  simplificationTolerance={2}
  onPolylinePress={() => console.log('Polyline pressed')}
/>

Polygon

Props

PropertyTypeDefaultDescription
pointsLatLngPoint[] | LatLngPoint[][]-Polygon coordinates, supports holes
strokeWidthnumber-Stroke width
strokeColorColorValue-Stroke color
fillColorColorValue-Fill color
zIndexnumber-Z index
simplificationTolerancenumber-Boundary simplification tolerance in meters

Events

EventParametersDescription
onPolygonPressNativeSyntheticEvent<{}>Polygon tap
onPolygonSimplifiedNativeSyntheticEvent<{ originalCount: number; simplifiedCount: number }>Simplification finished

Example

tsx
<Polygon
  points={[
    [
      { latitude: 39.9, longitude: 116.3 },
      { latitude: 39.9, longitude: 116.5 },
      { latitude: 39.8, longitude: 116.5 },
      { latitude: 39.8, longitude: 116.3 },
    ],
    [
      { latitude: 39.87, longitude: 116.37 },
      { latitude: 39.87, longitude: 116.43 },
      { latitude: 39.83, longitude: 116.43 },
      { latitude: 39.83, longitude: 116.37 },
    ],
  ]}
  fillColor="#5533AAFF"
  strokeColor="#FF1677FF"
  strokeWidth={2}
  onPolygonSimplified={(e) => console.log(e.nativeEvent)}
/>

Circle

Props

PropertyTypeDefaultDescription
centerLatLngPoint-Center coordinate, required
radiusnumber-Radius in meters, required
strokeWidthnumber-Stroke width
strokeColorColorValue-Stroke color
fillColorColorValue-Fill color
zIndexnumber-Z index

Events

EventParametersDescription
onCirclePressNativeSyntheticEvent<{}>Circle tap

Example

tsx
<Circle
  center={{ latitude: 39.9, longitude: 116.4 }}
  radius={1000}
  fillColor="#2200FF00"
  strokeColor="#FF00AA00"
  strokeWidth={2}
  onCirclePress={() => console.log('Circle pressed')}
/>

HeatMap

Props

PropertyTypeDefaultDescription
dataLatLngPoint[]-Heat points, required
visiblebooleantrueWhether the heatmap is visible
radiusnumber-Heat radius in meters
opacitynumber-Opacity between 0 ~ 1
gradient{ colors: ColorValue[]; startPoints: number[] }-Gradient configuration
allowRetinaAdaptingbooleanfalseRetina heatmap support, iOS only

Example

tsx
<HeatMap
  data={[
    { latitude: 39.9, longitude: 116.4 },
    { latitude: 39.91, longitude: 116.41 },
    { latitude: 39.92, longitude: 116.42 },
  ]}
  radius={40}
  opacity={0.7}
  gradient={{
    colors: ['#00F5FF', '#00FF7F', '#FFFF00', '#FF4500'],
    startPoints: [0.2, 0.4, 0.7, 1.0],
  }}
/>

MultiPoint

Best for rendering large static point datasets more efficiently than individual Marker components.

MultiPointItem

ts
interface MultiPointItem {
  latitude: number;
  longitude: number;
  id?: string | number;
  data?: unknown;
}

Props

PropertyTypeDefaultDescription
pointsMultiPointItem[]-Massive point list, required
iconstring | ImageSourcePropType-Shared icon
iconWidthnumber-Icon width
iconHeightnumber-Icon height

Events

EventParametersDescription
onMultiPointPressNativeSyntheticEvent<{ index: number; item: MultiPointItem }>Tap one point

Example

tsx
<MultiPoint
  points={[
    { id: 1, latitude: 39.9, longitude: 116.4, data: { name: 'A' } },
    { id: 2, latitude: 39.91, longitude: 116.41, data: { name: 'B' } },
  ]}
  icon="https://example.com/pin.png"
  iconWidth={24}
  iconHeight={24}
  onMultiPointPress={(e) => console.log(e.nativeEvent.item)}
/>

Cluster

ClusterPoint

ts
interface ClusterPoint {
  latitude?: number;
  longitude?: number;
  position?: LatLngPoint;
  properties?: Record<string, unknown>;
}

Props

PropertyTypeDefaultDescription
pointsClusterPoint[]-Cluster points, required
iconstring-Base cluster icon. Supports HTTP/HTTPS URL, file:// path, or bundle image name
radiusnumber-Cluster radius
minClusterSizenumber-Minimum number of points to form a cluster
clusterStyleViewStyle-Base cluster style
clusterBuckets({ minPoints: number } & ViewStyle)[]-Tiered cluster style rules
clusterTextStyleTextStyle-Cluster count text style
renderMarker(item: ClusterPoint) => React.ReactNode-Not implemented yet
renderCluster(params: ClusterParams) => React.ReactNode-Not implemented yet

Events

EventParametersDescription
onClusterPressNativeSyntheticEvent<ClusterParams>Tap a cluster

ClusterParams

ts
interface ClusterParams {
  count: number;
  latitude: number;
  longitude: number;
  pois?: ClusterPoint[];
  id?: number;
  position?: LatLng;
}

Example

tsx
<Cluster
  points={[
    { latitude: 39.9, longitude: 116.4, properties: { id: 1 } },
    { latitude: 39.901, longitude: 116.401, properties: { id: 2 } },
    { position: [116.402, 39.902], properties: { id: 3 } },
  ]}
  radius={30}
  minClusterSize={2}
  clusterStyle={{
    width: 36,
    height: 36,
    borderRadius: 18,
    backgroundColor: '#1677FF',
    alignItems: 'center',
    justifyContent: 'center',
  }}
  clusterTextStyle={{
    color: '#fff',
    fontSize: 12,
    fontWeight: '600',
  }}
  clusterBuckets={[
    { minPoints: 1, backgroundColor: '#00BFFF' },
    { minPoints: 10, backgroundColor: '#FFA500' },
    { minPoints: 50, backgroundColor: '#FF4500' },
  ]}
  onClusterPress={(e) => console.log(e.nativeEvent.count)}
/>

Color formats

Overlay colors support:

  • '#AARRGGBB'
  • '#RRGGBB'
  • 'red' / 'rgba(...)'
  • Android also supports numeric colors such as 0xFF1677FF

Combined example

tsx
import {
  MapView,
  Marker,
  Polyline,
  Polygon,
  Circle,
  HeatMap,
  MultiPoint,
  Cluster,
} from 'expo-gaode-map';

export default function OverlaysExample() {
  return (
    <MapView
      style={{ flex: 1 }}
      initialCameraPosition={{
        target: { latitude: 39.9, longitude: 116.4 },
        zoom: 11,
      }}
    >
      <Circle center={{ latitude: 39.9, longitude: 116.4 }} radius={1000} />
      <Marker position={{ latitude: 39.92, longitude: 116.42 }} title="Marker" />
      <Polyline
        points={[
          { latitude: 39.9, longitude: 116.4 },
          { latitude: 39.95, longitude: 116.45 },
        ]}
        strokeWidth={4}
        strokeColor="#1677FF"
      />
      <Polygon
        points={[
          { latitude: 39.85, longitude: 116.35 },
          { latitude: 39.85, longitude: 116.45 },
          { latitude: 39.75, longitude: 116.4 },
        ]}
        fillColor="#2200AAFF"
      />
      <HeatMap
        data={[
          { latitude: 39.91, longitude: 116.38 },
          { latitude: 39.92, longitude: 116.39 },
        ]}
      />
    </MapView>
  );
}