Clustered Features
See https://openlayers.org/en/latest/examples/cluster.html
import React, { useState, memo } from "react";
import "ol/ol.css";
import { Style, Circle as CircleStyle, Fill, Stroke, Text } from "ol/style";
import { Map } from "@react-ol/fiber";
export const coordinates = (() => {
const count = 20000;
const e = 4500000;
const coordinates = new Array(count);
for (let i = 0; i < count; i++) {
coordinates[i] = [2 * e * Math.random() - e, 2 * e * Math.random() - e];
}
return coordinates;
})();
export const styleCache = [];
export const PointsAtCoordinates = memo(({ coordinates }) => {
// It is important to memoize this, to avoid iterating over all the coordinates
// on each react render if the array is not changed.
return coordinates.map((coordinate) => (
<olFeature key={coordinate.join()}>
<olGeomPoint args={[coordinate]} />
</olFeature>
));
});
export const ExampleCluster = () => {
const [distance, setDistance] = useState(40);
const [minDistance, setMinDistance] = useState(20);
return (
<>
<form>
<label htmlFor="distance">Cluster distance</label>
<input
id="distance"
type="range"
min="0"
max="100"
step="1"
value={distance}
onChange={(e) => setDistance(parseInt(e.target.value, 10))}
/>
<label htmlFor="minDistance">Minimum distance</label>
<input
id="minDistance"
type="range"
min="0"
max="100"
step="1"
value={minDistance}
onChange={(e) => setMinDistance(parseInt(e.target.value, 10))}
/>
</form>
<Map>
<olView initialCenter={[0, 0]} initialZoom={2} />
<olLayerTile>
<olSourceOSM />
</olLayerTile>
<olLayerVector
style={(feature) => {
const size = feature.get("features").length;
let style = styleCache[size];
if (!style) {
style = new Style({
image: new CircleStyle({
radius: 10,
stroke: new Stroke({
color: "#fff",
}),
fill: new Fill({
color: "#3399CC",
}),
}),
text: new Text({
text: size.toString(),
fill: new Fill({
color: "#fff",
}),
}),
});
styleCache[size] = style;
}
return style;
}}
>
<olSourceCluster distance={distance} minDistance={minDistance}>
<olSourceVector>
<PointsAtCoordinates coordinates={coordinates} />
</olSourceVector>
</olSourceCluster>
</olLayerVector>
</Map>
</>
);
};