两个图层共用一个 source,改一个另一个也变
主图上的“已选站点”清空了,对比窗口里的同一批点也消失了,两个地图明明互不相关。
现象
主视图与对比视图各自建了 VectorLayer,但把同一个
VectorSource 传给了两个图层。之后:
- 在 A 图层
source.clear(),B 图层的要素同时消失。 - 给 A 图层添加要素,B 图层立即出现相同的要素。
- 两个地图的视图投影不同时,B 图层的要素整体偏移。
- 对要素调用
setStyle,两个图层的样式一起改变。
原因
VectorSource 是数据容器,不是图层的一部分。
它自己持有要素集合与一个 projection,多个图层引用同一个实例时,
共享的是同一份要素对象与同一套空间参考。
source.clear() 会移除并销毁要素,图层只是“看到”了数据变化,
自然同时清空。要素上的样式与几何也是共享的,一处修改处处生效。
排查过程
打印两个图层的 source 是否同一个对象,以及各自的投影:
console.log(layerA.getSource() === layerB.getSource()); // true,就是问题所在
console.log(layerA.getSource().getProjection());
console.log(mapA.getView().getProjection().getCode());
console.log(mapB.getView().getProjection().getCode());
解决方案
每个图层一个独立 source。需要相同数据时,克隆要素而不是克隆 source:
var featuresA = sourceA.getFeatures();
var featuresB = featuresA.map(function (f) {
return f.clone();
});
var sourceB = new ol.source.Vector({ features: featuresB });
var layerB = new ol.layer.Vector({ source: sourceB });
同一份数据要显示两种样式(选中态与普通态)时,用 style
区分即可,不必复制数据,但不要在两个图层之间共享“可编辑”的要素:
var shared = new ol.source.Vector({ features: features });
var normalLayer = new ol.layer.Vector({
source: shared,
style: normalStyle
});
var highlightLayer = new ol.layer.Vector({
source: shared,
style: highlightStyle,
declutter: true
});
两个地图的视图投影不同时,必须各自建 source,并在正确的投影下写入坐标。
用 readFeatures 的 dataProjection 与
featureProjection 明确转换:
var format = new ol.format.GeoJSON();
var sourceB = new ol.source.Vector({
features: format.readFeatures(geojson, {
dataProjection: 'EPSG:4326',
featureProjection: mapB.getView().getProjection()
})
});
验证
layerA.getSource() !== layerB.getSource()。
在 A 图层清空后,B 图层要素数量不变。
两个地图缩放、平移互不影响,要素位置各自正确。
判断标准:source 的生命周期应与图层一致。 一个 source 被两个图层引用,就要预期“任何一方的修改都会影响另一方”。 需要独立行为时,从数据层复制,而不是从容器层共享。
经纬志(2026)。《两个图层共用一个 source,改一个另一个也变》。https://www.jingweizhi.com/cookbook/ol-source-reuse-pollution.html(访问日期 2026-11-03)。