Skip to main content
Api

<ScriptGoogleMapsMarkerClusterer>

Groups nearby markers into clusters at lower zoom levels. Place it inside a <ScriptGoogleMaps> component. Google's marker clustering guide explains the library and its accessibility rationale.

optionsOmit<MarkerClustererOptions, 'map'>

Configuration options for the marker clusterer.

Installation

Requires the @googlemaps/markerclusterer peer dependency:

pnpm add @googlemaps/markerclusterer

Usage

Child markers register and unregister themselves automatically.

<script setup lang="ts">
const locations = ref([
  { id: 1, name: 'Sydney Opera House', position: { lat: -33.8568, lng: 151.2153 } },
  { id: 2, name: 'Bondi Beach', position: { lat: -33.8908, lng: 151.2743 } },
  { id: 3, name: 'Taronga Zoo', position: { lat: -33.8433, lng: 151.2411 } },
])
</script>

<template>
  <ScriptGoogleMaps
    api-key="your-api-key"
    :map-options="{
      center: { lat: -33.86, lng: 151.24 },
      zoom: 12,
    }"
  >
    <ScriptGoogleMapsMarkerClusterer>
      <ScriptGoogleMapsMarker
        v-for="location in locations"
        :key="location.id"
        :position="location.position"
      >
        <ScriptGoogleMapsInfoWindow>
          <div>{{ location.name }}</div>
        </ScriptGoogleMapsInfoWindow>
      </ScriptGoogleMapsMarker>
    </ScriptGoogleMapsMarkerClusterer>
  </ScriptGoogleMaps>
</template>

Dynamic Markers

Markers added or removed reactively (e.g., via v-for with a changing list) automatically register with and unregister from the clusterer.

<script setup lang="ts">
const locations = ref([/* initial locations */])

function addLocation(position: google.maps.LatLngLiteral) {
  locations.value.push({ id: Date.now(), name: 'New', position })
}
</script>

<template>
  <ScriptGoogleMaps api-key="your-api-key">
    <ScriptGoogleMapsMarkerClusterer>
      <ScriptGoogleMapsMarker
        v-for="loc in locations"
        :key="loc.id"
        :position="loc.position"
      />
    </ScriptGoogleMapsMarkerClusterer>
  </ScriptGoogleMaps>
</template>

Custom Algorithm

Pass algorithm through options to customize clustering behavior. See the @googlemaps/markerclusterer documentation for available algorithms.

The component reads options when it creates the clusterer and does not watch the prop afterward. Remount it to change the algorithm or other clusterer options at runtime.

<script setup lang="ts">
import { SuperClusterAlgorithm } from '@googlemaps/markerclusterer'

const clustererOptions = {
  algorithm: new SuperClusterAlgorithm({ radius: 200 }),
}
</script>

<template>
  <ScriptGoogleMaps api-key="your-api-key">
    <ScriptGoogleMapsMarkerClusterer :options="clustererOptions">
      <ScriptGoogleMapsMarker
        v-for="loc in locations"
        :key="loc.id"
        :position="loc.position"
      />
    </ScriptGoogleMapsMarkerClusterer>
  </ScriptGoogleMaps>
</template>

Custom Cluster Renderer

Use the #renderer slot to customize how clusters look using Vue templates. The slot receives cluster (with count, position, markers), stats, and map (the Google Maps instance).

<template>
  <ScriptGoogleMaps api-key="your-api-key">
    <ScriptGoogleMapsMarkerClusterer>
      <template #renderer="{ cluster }">
        <div
          style="
            background: #4285f4;
            color: white;
            border-radius: 50%;
            width: 40px;
            height: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-weight: bold;
          "
        >
          {{ cluster.count }}
        </div>
      </template>

      <ScriptGoogleMapsMarker
        v-for="loc in locations"
        :key="loc.id"
        :position="loc.position"
      />
    </ScriptGoogleMapsMarkerClusterer>
  </ScriptGoogleMaps>
</template>

The #renderer slot overrides the renderer option. Each cluster gets its own AdvancedMarkerElement with the slot content as its visual.

The clusterer only renders its default slot after the clusterer instance is ready. This prevents child markers from mounting before the clusterer can receive them.