Clusters 聚类
使用 MapLibre 内置聚类高效渲染大量点数据。点在低缩放级别自动分组为聚类,随缩放展开。
MapClusterLayer 组件使用 MapLibre GL 的原生聚类功能。 自动将附近的点分组为聚类,点击聚类时放大展开。必须在 Map 内部使用。
基本用法
点击聚类放大,点击单个点查看详情弹窗:
ClusterExample.tsx
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
class="tk-string">"use client";
import { useState } from class="tk-string">"react";
import { Map, MapClusterLayer, MapPopup, MapControls } from class="tk-string">"@/components/ui/map";
interface EarthquakeProperties {
mag: number;
place: string;
tsunami: number;
}
export function ClusterExample() {
const [selectedPoint, setSelectedPoint] = useState<{
coordinates: [number, number];
properties: EarthquakeProperties;
} | null>(null);
return (
<div className=class="tk-string">"h-[420px] w-full">
<Map center={[-103.59, 40.66]} zoom={3.4} fadeDuration={0}>
<MapClusterLayer<EarthquakeProperties>
data=class="tk-string">"https:class="tk-commentclass="tk-string">">//maplibre.org/maplibre-gl-js/docs/assets/earthquakes.geojson"
clusterRadius={50}
clusterMaxZoom={14}
clusterColors={[class="tk-string">"#1d8cf8", class="tk-string">"#6d5dfc", class="tk-string">"#e23670"]}
pointColor=class="tk-string">"#1d8cf8"
onPointClick={(feature, coordinates) => {
setSelectedPoint({
coordinates,
properties: feature.properties,
});
}}
/>
{selectedPoint && (
<MapPopup
key={class="tk-string">`${selectedPoint.coordinates[0]}-${selectedPoint.coordinates[1]}`}
longitude={selectedPoint.coordinates[0]}
latitude={selectedPoint.coordinates[1]}
onClose={() => setSelectedPoint(null)}
closeOnClick={false}
focusAfterOpen={false}
closeButton
className=class="tk-string">"w-34"
>
<div className=class="tk-string">"text-[13px]">
<p className=class="tk-string">"text-muted-foreground">
震级:{class="tk-string">" "}
<span className=class="tk-string">"text-foreground font-medium">
{selectedPoint.properties.mag}
</span>
</p>
<p className=class="tk-string">"text-muted-foreground">
海啸:{class="tk-string">" "}
<span className=class="tk-string">"text-foreground font-medium">
{selectedPoint.properties?.tsunami === 1 ? class="tk-string">"是" : class="tk-string">"否"}
</span>
</p>
</div>
</MapPopup>
)}
<MapControls />
</Map>
</div>
);
}自定义聚类颜色
clusterColors 定义三个级别的聚类颜色,clusterThresholds 定义点数阈值:
12345678910
<MapClusterLayer
data={earthquakeData}
clusterColors={[
class="tk-string">"#22c55e", class=class="tk-string">"tk-comment">// 小聚类(< 100 个点)
class="tk-string">"#eab308", class=class="tk-string">"tk-comment">// 中聚类(100-750 个点)
class="tk-string">"#ef4444", class=class="tk-string">"tk-comment">// 大聚类(> 750 个点)
]}
clusterThresholds={[100, 750]}
pointColor=class="tk-string">"#3b82f6"
/>自定义聚类点击
默认点击聚类会放大展开。你也可以自定义点击行为:
1234567
<MapClusterLayer
data={data}
onClusterClick={(clusterId, coordinates, pointCount) => {
console.log(class="tk-string">`聚类 ${clusterId} 包含 ${pointCount} 个点`);
class=class="tk-string">"tk-comment">// 自定义逻辑,如显示聚类详情弹窗
}}
/>类型安全
使用泛型类型参数实现类型安全的属性访问:
1234567891011121314
interface StoreProperties {
name: string;
category: string;
isOpen: boolean;
}
<MapClusterLayer<StoreProperties>
data={storesGeoJSON}
onPointClick={(feature, coordinates) => {
class=class="tk-string">"tk-comment">// feature.properties 类型为 StoreProperties
console.log(feature.properties.name);
console.log(feature.properties.isOpen);
}}
/>属性
| 属性 | 类型 | 默认值 | 描述 |
|---|---|---|---|
data | string | GeoJSON.FeatureCollection | — | GeoJSON 数据或获取数据的 URL |
clusterMaxZoom | number | 14 | 聚类点的最大缩放级别 |
clusterRadius | number | 50 | 聚类点半径(像素) |
clusterColors | [string, string, string] | 绿/黄/红 | 聚类圆颜色:[小, 中, 大] |
clusterThresholds | [number, number] | [100, 750] | 颜色/大小阈值:[中, 大] |
pointColor | string | "#3b82f6" | 未聚类的单点颜色 |
onPointClick | (feature, coordinates) => void | — | 单个点被点击时的回调 |
onClusterClick | (clusterId, coordinates, pointCount) => void | 放大展开 | 聚类被点击时的回调。未提供时自动放大 |
下一步
高级用法