polyline-api
本文回答:Polyline / 底座图元的"单独建 source + 图层"写法 ——
addGeoJSONSource/addLineLayer/addFillLayer/addCircleLayer/addSymbolLayer。
一、为什么要单独建 source
new vjmap.Polyline({ data }) 会把 source 和 layer 放在一起创建,同一份数据只渲染一种样式。
但如果需要:
- 同一份 GeoJSON 同时渲染 fill + line + symbol(三种样式共享数据)
- 程序动态切换不同 layer
- 多图层共享 source,setData 一次全部更新
→ 需要单独建 source,然后挂多个 layer。
二、addGeoJSONSource
map.addGeoJSONSource("my-src", {
type: "FeatureCollection",
features: [...]
});
// 等价于
map.addSource("my-src", {
type: "geojson",
data: { type: "FeatureCollection", features: [...] }
});
常用选项:
map.addSource("my-src", {
type: "geojson",
data: geojson,
generateId: true, // 自动生成 feature.id(feature-state 要用)
cluster: true, // 点聚合
clusterRadius: 50,
clusterMaxZoom: 14,
clusterProperties: {
sumValue: ["+", ["get", "value"]]
},
lineMetrics: true, // 给 line-gradient 用
tolerance: 0.375 // 简化容差(默认)
});
三、addLineLayer(不用区分 layout/paint)
map.addLineLayer("my-line", "my-src", {
lineCap: "round",
lineJoin: "round",
lineColor: "#f00",
lineWidth: 3,
filter: ["==", ["geometry-type"], "LineString"]
});
四、addFillLayer
map.addFillLayer("my-fill", "my-src", {
fillColor: "#0af",
fillOpacity: 0.6,
fillOutlineColor: "#003",
filter: ["==", ["geometry-type"], "Polygon"]
});
五、addCircleLayer
map.addCircleLayer("my-circle", "my-src", {
circleColor: "#f00",
circleRadius: 5,
filter: ["==", ["geometry-type"], "Point"]
});
六、addSymbolLayer
map.addSymbolLayer("my-sym", "my-src", {
iconImage: ["get", "icon"],
textField: ["get", "name"],
textSize: 12,
filter: ["==", ["geometry-type"], "Point"]
});
七、同一 source 三种样式
map.addGeoJSONSource("features", mixedGeoJson);
map.addFillLayer("features-poly", "features", {
fillColor: "#0af",
fillOpacity: 0.4,
filter: ["==", ["geometry-type"], "Polygon"]
});
map.addLineLayer("features-line", "features", {
lineColor: "#f00",
lineWidth: 2,
filter: ["==", ["geometry-type"], "LineString"]
});
map.addCircleLayer("features-pt", "features", {
circleColor: "#f00",
circleRadius: 5,
filter: ["==", ["geometry-type"], "Point"]
});
// 一次更新所有图层
map.getSource("features").setData(newGeoJson);
八、事件 —— 单独建的 layer 用 map.on 而不是 clickLayer
map.on("click", "my-line", e => {
console.log(e.features[0]);
});
map.on("mouseenter", "my-line", () => map.getCanvas().style.cursor = "pointer");
map.on("mouseleave", "my-line", () => map.getCanvas().style.cursor = "");
九、层序控制
// beforeId 参数决定插入位置
map.addLineLayer("my-line", "my-src", {...}, "other-layer-id");
// 或移动层序
map.moveLayer("my-line", "building-layer"); // 放在 building-layer 下面
map.moveLayer("my-line"); // 移到最上
十、移除
map.removeLayer("my-line");
map.removeSource("my-src");
// vjmap 扩展:一次移除 layer + 无人使用的 source
map.removeSourceEx("my-src");
十一、何时用封装类 vs 手写
| 场景 | 推荐 |
|---|---|
| 单图层,快速开发 | new vjmap.Polyline / Polygon / Circle 等 |
| 同 source 多图层 | addGeoJSONSource + add*Layer |
| 复杂表达式调试 | addLayer(原生) |
| 框架里批量管理 | 统一用 addGeoJSONSource 更可控 |
十二、常见坑
- layerId 冲突 → 先
map.getLayer("id") && map.removeLayer("id")。 - addSymbolLayer 图标不显示 → 图标名
loadImage了吗。 - 多图层 click 冒泡 →
map.on("click", "layerA", ...)只在该层 hit 时触发;如果要"所有层共用一个 handler",用map.queryRenderedFeatures(e.point, { layers: [...] })。