geojson-source
本文回答:GeoJSON source 全面用法 —— addSource / setData / 属性更新 / cluster / lineMetrics / filter。
一、创建 GeoJSON source
map.addSource("mySrc", {
type: "geojson",
data: featureCollection
});
// 或 URL
map.addSource("mySrc", {
type: "geojson",
data: "https://example.com/a.geojson"
});
// vjmap 扩展:
map.addGeoJSONSource("mySrc", featureCollection);
二、source 选项
| 选项 | 默认 | 说明 |
|---|---|---|
data |
— | GeoJSON / URL |
generateId |
false | 为 feature 自动生成 id,feature-state 必需 |
lineMetrics |
false | 计算线进度,line-gradient 必需 |
cluster |
false | 启用点聚合 |
clusterRadius |
50 | 聚合半径(像素) |
clusterMaxZoom |
— | 超过该 zoom 不聚合 |
clusterMinPoints |
2 | 最少几点算一簇 |
clusterProperties |
— | 聚合时的属性聚合函数 |
tolerance |
0.375 | 简化容差 |
buffer |
128 | 瓦片缓冲 |
maxzoom |
18 | 切瓦片的最大 zoom |
attribution |
— | 版权文字 |
promoteId |
— | 提升某个属性为 id |
三、更新数据 setData
map.getSource("mySrc").setData(newFeatureCollection);
// 小修改 → 传新 FC,一次性替换
注意:GeoJSON source 没有 "patch",每次都要传完整数据。如果只改几十个 feature,最好在前端缓存副本。
四、按 promoteId 把属性当 id
map.addSource("mySrc", {
type: "geojson",
data,
promoteId: "gid" // feature.properties.gid → feature.id
});
// 之后就可 setFeatureState
map.setFeatureState(
{ source: "mySrc", id: 123 },
{ hover: true }
);
五、feature-state API
// 读
const state = map.getFeatureState({ source: "mySrc", id: 123 });
// 写
map.setFeatureState({ source: "mySrc", id: 123 }, { hover: true });
// 清除单 feature
map.removeFeatureState({ source: "mySrc", id: 123 }, "hover");
// 清除整 source
map.removeFeatureState({ source: "mySrc" });
六、query 所有 feature
// 整源查
const feats = map.querySourceFeatures("mySrc");
// 屏幕上可见的(必须指定图层)
const rendered = map.queryRenderedFeatures(e.point, { layers: ["layer1"] });
// 按 filter 查
const subset = map.querySourceFeatures("mySrc", {
filter: ["==", ["get", "type"], "POI"]
});
七、cluster 聚合点
map.addSource("pts", {
type: "geojson",
data: pointFc,
cluster: true,
clusterRadius: 50,
clusterMaxZoom: 14,
clusterProperties: {
sum: ["+", ["get", "val"]]
}
});
map.addLayer({
id: "clusters", type: "circle", source: "pts",
filter: ["has", "point_count"],
paint: {
"circle-radius": ["step", ["get", "point_count"], 15, 10, 20, 50, 25],
"circle-color": ["step", ["get", "point_count"], "#0f0", 10, "#ff0", 50, "#f00"]
}
});
map.addLayer({
id: "cluster-count", type: "symbol", source: "pts",
filter: ["has", "point_count"],
layout: {
"text-field": ["get", "point_count_abbreviated"],
"text-size": 12
}
});
map.addLayer({
id: "unclustered", type: "circle", source: "pts",
filter: ["!", ["has", "point_count"]],
paint: { "circle-radius": 5, "circle-color": "#11b4da" }
});
// 点击展开
map.on("click", "clusters", e => {
const feat = e.features[0];
const cid = feat.properties.cluster_id;
map.getSource("pts").getClusterExpansionZoom(cid, (err, zoom) => {
if (err) return;
map.easeTo({ center: feat.geometry.coordinates, zoom });
});
});
八、lineMetrics 用法
map.addSource("route", {
type: "geojson",
data: lineFc,
lineMetrics: true // 必须
});
map.addLineLayer("route-line", "route", {
lineWidth: 6,
lineGradient: [
"interpolate", ["linear"], ["line-progress"],
0, "#0f0",
1, "#f00"
]
});
九、GeoJSON 格式小抄
// Point
{ type: "Point", coordinates: [x, y] }
// LineString
{ type: "LineString", coordinates: [[x,y],[x,y]] }
// Polygon(外环 + 多个孔)
{ type: "Polygon", coordinates: [
[[x,y],[x,y],...,[x,y]], // 外
[[x,y],...,[x,y]] // 孔(可选)
]}
// MultiPolygon
{ type: "MultiPolygon", coordinates: [
[ [外], [孔] ],
[ [外] ]
]}
// FeatureCollection
{ type: "FeatureCollection", features: [
{ type: "Feature", geometry: {...}, properties: {...}, id: 1 }
]}
十、geometry-type 过滤
在多几何混合 source 上,按几何类型分图层:
map.addFillLayer("poly", "mySrc", {
fillColor: "#0af",
filter: ["==", ["geometry-type"], "Polygon"]
});
map.addLineLayer("line", "mySrc", {
lineColor: "#f00",
filter: ["==", ["geometry-type"], "LineString"]
});
map.addCircleLayer("pt", "mySrc", {
circleColor: "#f00",
filter: ["==", ["geometry-type"], "Point"]
});
注意:老写法是 ["==", "$type", "LineString"],新写法 ["==", ["geometry-type"], "LineString"]。
十一、常见坑
- setData 整份数据大 → 卡顿 → cluster / 切瓦片 / 按视野分片加载。
- feature-state 不生效 → 没 id(
generateId: true或promoteId)。 - URL data 跨域 → 后端加 CORS。
- 很多小的 source → 合并成一个带 filter 的 source,性能更好。
- updates 时图层闪烁 → 先
setData再渲染帧;别在每帧 setData。 querySourceFeatures返回空:geojson 的瓦片索引只在有图层引用该 source 且视口覆盖到数据时才生成——只addSource不加图层、或数据在当前视口外,查询恒返回[]。且setData后旧瓦片会先命中(新瓦片异步重建),需要按数量/内容轮询而非查一次。