The most comprehensive and yet easiest to use react native point clustering library. Uses c++ implementation of supercluster and JSI bindings for up to 10x faster initial point loading times than its JavaScript counterpart.
npm install react-native-clusterer
# iOS
cd ios && pod install
Check out the example folder for a fully functional example and speed comparisons. On android make sure to update AndroidManifest.xml with com.google.android.geo.API_KEY meta data in order for Google Maps to work.
This library provides three different ways to use Supercluster based on your needs:
- useClusterer: Hook for most hassle-free implementation.
- Clusterer: React Native component.
- Supercluster: Class for custom functionality.
If you are looking for a JS drag-and-drop replacement to speed up point clustering, you should be aware of some caveats:
- Currently supported Point properties are
null
,boolean
,number
,string
. The rest will be discarded when the supercluster is created. If you need to store other properties you can always turn them into a JSON. - The
destroy()
method has to be called every time Supercluster instance is discarded.useClusterer
andCluster
will take care of this for you. - Missing
Map/reduce
functionality.
import { useClusterer } from 'react-native-clusterer';
const MAP_DIMENSIONS = { width: MAP_WIDTH, height: MAP_HEIGHT }
//...
const [region, setRegion] = useState(initialRegion);
const [points, supercluster] = useClusterer(
markers,
MAP_DIMENSIONS,
regions
);
// ...
return (
<MapView
onRegionChangeComplete={setRegion}
// ... other props
>
{points.map(point => (
// These should be memoized components,
// otherwise you might see flickering
<Marker
// ... marker props
>
{/*
// ... marker children - callout, custom marker, etc.
*/}
</Marker>
);
)}
/>
</MapView>
);
Same as points passed to supercluster.load()
.
Object containing width
and height
of the <MapView />
Component
Region from the <MapView />
Component: Object containing latitude
, longitude
, latitudeDelta
and longitudeDelta
values.
Same as options for Supercluster, not required.
An array with two elements:
points
- Array of points (GeoJSON Feature point or cluster
). Clusters have an additional getClusterExpansionRegion() which will return a region that can be used to expand the cluster. Same as expandCluster without the need forclusterId
param.supercluster
- Supercluster instance.
//...
import { Clusterer } from 'react-native-clusterer';
import MapView, { Marker } from 'react-native-maps';
const MAP_DIMENSIONS = { width: MAP_WIDTH, height: MAP_HEIGHT }
// ...
const [markers, setMarkers] = useState([]);
const [region, setRegion] = useState(initialRegion);
// ...
return (
<MapView
onRegionChangeComplete={setRegion}
// ... other props
>
<Clusterer
data={markers}
region={region}
options={DEFAULT_OPTIONS}
mapDimensions={MAP_DIMENSIONS}
renderItem={(item) => {
return (
// These should be memoized components,
// otherwise you might see flickering
<Marker
// ... marker props
>
{/* marker children - callout, custom marker, etc. */}
{item.properties.cluster_id ? (
// render cluster
) : (
// render marker
)}
</Marker>
);
}}
/>
</MapView>
);
Same as points passed to supercluster.load()
.
Object containing width
and height
of the <MapView />
Component
Region from the <MapView />
Component: Object containing latitude
, longitude
, latitudeDelta
and longitudeDelta
values.
Same as options for Supercluster.
Function that takes an item (GeoJSON Feature point or cluster
) and returns a Marker component. renderItem
additionally provides function getClusterExpansionRegion() inside properies for clusters (ONLY for clusters!) which will return a region that can be used to expand the cluster. Same as expandCluster without the need for clusterId
param.
import Supercluster from 'react-native-clusterer';
//...
// Create a new instance of Supercluster
const supercluster = new Supercluster(options);
// Load points
supercluster.load(points);
// Get clusters
supercluster.getClustersFromRegion(region, mapDimensions);
// Once you are done using the instance, call destroy() to free up memory.
supercluster.destroy();
Option | Default | Description |
---|---|---|
minZoom | 0 | Minimum zoom level at which clusters are generated. |
maxZoom | 16 | Maximum zoom level at which clusters are generated. |
minPoints | 2 | Minimum number of points to form a cluster. |
radius | 40 | Cluster radius, in pixels. |
extent | 512 | (Tiles) Tile extent. Radius is calculated relative to this value. |
generateId | false | Whether to generate ids for input features in vector tiles. |
Loads an array of GeoJSON Feature objects. Each feature's geometry
must be a GeoJSON Point. Once loaded, index is immutable.
For the given bbox
array ([westLng, southLat, eastLng, northLat]
) and integer zoom
, returns an array of clusters and points as GeoJSON Feature objects.
For the given region
from react-native-maps <MapView />
and an object containing width
and height
of the component, returns an array of clusters and points as GeoJSON Feature objects.
For a given zoom and x/y coordinates, returns a geojson-vt-compatible JSON tile object with cluster/point features.
Returns the children of a cluster (on the next zoom level) given its id (clusterId
value from feature properties).
Returns all the points of a cluster (given its clusterId
), with pagination support:
limit
is the number of points to return, and offset
is the number of points to skip (for pagination).
Returns the zoom on which the cluster expands into several children (useful for "click to zoom" feature) given the cluster's clusterId
.
Returns a region containing the center of all the points in a cluster and the delta value by which it should be zoomed out to see all the points. Useful for animating a MapView after a cluster press.
IMPORTANT: Since JS doesnt have destructors, we have to make sure the cluster stored in c++ memory is also deleted. This method is called automatically when using the <Clusterer />
component. Open to any suggestions for Class implementation.
- Proper input and return types for methods
- Implement
getClusters(bbox, zoom)
- Parse and return additional Point properties added by users
- Find a better implementation for
destroy()
. - Map/reduce options
See the contributing guide to learn how to contribute to the repository and the development workflow.
MIT
Copyright (c) 2021 Jiri Hoffmann
Uses supercluster for point clustering. Check out mapbox/supercluster.hpp for additional licensing.