Map Circle Cluster
terrae/circle-clusterFreeComponent
Marker clustering with circle visualization.
Install it
npx shadcn@latest add https://www.terrae.dev/circle-cluster.jsonSource
1"use client"23import { useEffect, useId, useRef } from "react"4import type mapboxgl from "mapbox-gl"5import { useMap } from "./hooks"6import type { MapCoordinates } from "./types"78type MapCircleClusterProps<P extends GeoJSON.GeoJsonProperties = GeoJSON.GeoJsonProperties> = {9 /** GeoJSON FeatureCollection data or URL to fetch GeoJSON from */10 data: string | GeoJSON.FeatureCollection<GeoJSON.Point, P>11 /** Maximum zoom level to cluster points on (default: 14) */12 clusterMaxZoom?: number13 /** Radius of each cluster when clustering points in pixels (default: 50) */14 clusterRadius?: number15 /** Colors for cluster circles: [small, medium, large] based on point count (default: ["#51bbd6", "#f1f075", "#f28cb1"]) */16 clusterColors?: [string, string, string]17 /** Point count thresholds for color/size steps: [medium, large] (default: [100, 750]) */18 clusterThresholds?: [number, number]19 /** Color for unclustered individual points (default: "#3b82f6") */20 pointColor?: string21 /** Callback when an unclustered point is clicked */22 onPointClick?: (feature: GeoJSON.Feature<GeoJSON.Point, P>, coordinates: MapCoordinates) => void23 /** Callback when a cluster is clicked. If not provided, zooms into the cluster */24 onClusterClick?: (clusterId: number, coordinates: MapCoordinates, pointCount: number) => void25}2627export function MapCircleCluster<P extends GeoJSON.GeoJsonProperties = GeoJSON.GeoJsonProperties>({28 data,29 clusterMaxZoom = 14,30 clusterRadius = 50,31 clusterColors = ["#be123c", "#1d4ed8", "#f28cb1"],32 clusterThresholds = [100, 750],33 pointColor = "#3b82f6",34 onPointClick,35 onClusterClick,36}: MapCircleClusterProps<P>) {37 const { map, isLoaded } = useMap()38 const id = useId()39 const sourceId = `cluster-source-${id}`40 const clusterLayerId = `cluster-layer-${id}`41 const clusterCountLayerId = `cluster-count-${id}`42 const unclusteredLayerId = `unclustered-point-${id}`4344 const initializedRef = useRef(false)45 const stylePropsRef = useRef({46 clusterColors,47 clusterThresholds,48 pointColor,49 })5051 // Add source and layers on mount52 useEffect(() => {53 if (!isLoaded || !map || initializedRef.current) return54 if (!map.getContainer?.() || !map.getCanvasContainer?.() || !map.isStyleLoaded()) {55 return56 }5758 // Add clustered GeoJSON source59 map.addSource(sourceId, {60 type: "geojson",61 data: typeof data === "string" ? data : data,62 cluster: true,63 clusterMaxZoom,64 clusterRadius,65 })6667// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from terrae
All 40 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Map Animated Circleanimated-circle | terrae | Components | Free | 1 dep | |
| Map Animated Footprintanimated-footprint | terrae | Components | Free | 2 deps | |
| Map Animated Polygonanimated-polygon | terrae | Components | Free | 1 dep | |
| Map Animated Pulseanimated-pulse | terrae | Components | Free | 1 dep | |
| Map Arc Animatedarc-animated | terrae | Components | Free | 1 dep | |
| Map Blur Areablur-area | terrae | Components | Free | 1 dep | |
| Map Camera Followcamera-follow | terrae | Components | Free | 1 dep | |
| Map Choroplethchoropleth | terrae | Components | Free | 1 dep |
