Skip to content

Commit 8d92d89

Browse files
【fix】 修复ol fgb source 更改地图范围时重复添加要素,leaflet ol fgb 增加 idField参数 review by songym
1 parent ac1e19e commit 8d92d89

File tree

5 files changed

+58
-19
lines changed

5 files changed

+58
-19
lines changed

src/leaflet/overlay/FGBLayer.js

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ import { deserialize } from 'flatgeobuf/lib/mjs/geojson';
1919
* @param {Object} options - 参数。
2020
* @param {function} [options.pointToLayer] - 定义点要素如何绘制在地图上。
2121
* @param {function} [options.style] - 定义点、线、面要素样式。参数为{@link L.Path-option}。
22-
* @param {string} [options.strategy='bbox'] - 指定加载策略,可选值为 all,bbox。 all为全量加载, bbox为按需加载
22+
* @param {string} [options.strategy='bbox'] - all为全量加载,要素会以流的方式渲染到地图。 bbox为当前可见范围加载,当地图范围改变时会重新加载要素,此时可以通过idField 参数来标识已被加载过的要素,被标识的要素无需再次加载。idField 参数无效时会清空要素,重新加载
2323
* @param {Array} [options.extent] - 加载范围, 参数规范为: [minX, minY, maxX, maxY], 传递此参数后, 图层将使用局部加载。
24+
* @param {boolean} [options.idField='SmID'] - 是否指定要素字段作为唯一id,当 strategy 为 bbox 时生效。
2425
* @param {function} [options.featureLoader] - 要素自定义方法。
2526
* @param {function} [options.onEachFeature] - 要素创建时调用
2627
* @usage
@@ -49,6 +50,10 @@ export var FGBLayer = L.LayerGroup.extend({
4950
this.previousLayer = null;
5051
this.loadedExtentsRtree_ = new RBush();
5152
this.extent = this.options.extent;
53+
this._cacheIds = [];
54+
this._validatedId = false;
55+
this._checked = false;
56+
this.idField = this.options.idField || 'SmID';
5257
this._updateFeaturesFn = this._updateFeatures.bind(this);
5358
L.Util.setOptions(this, options);
5459
},
@@ -57,7 +62,7 @@ export var FGBLayer = L.LayerGroup.extend({
5762
let extent = [];
5863
if (this.strategy === 'bbox') {
5964
const bounds = map.getBounds();
60-
extent = [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()];
65+
extent = [bounds.getWest(), bounds.getSouth(), bounds.getEast(), bounds.getNorth()];
6166
map.on('moveend', this._updateFeaturesFn);
6267
}
6368

@@ -72,6 +77,7 @@ export var FGBLayer = L.LayerGroup.extend({
7277
this.loadedExtentsRtree_ = null;
7378
if (this.strategy === 'bbox') {
7479
map.off('moveend', this._updateFeaturesFn);
80+
this._cacheIds = [];
7581
}
7682
},
7783
_updateFeatures: async function (e) {
@@ -82,9 +88,7 @@ export var FGBLayer = L.LayerGroup.extend({
8288
return this._containsExtent(object.extent, extentToLoad);
8389
});
8490
if (!alreadyLoaded) {
85-
8691
this._handleFeatures(extentToLoad);
87-
8892
}
8993
},
9094
_handleFeatures: async function (extent) {
@@ -101,19 +105,33 @@ export var FGBLayer = L.LayerGroup.extend({
101105
rect.value = { extent: extent.slice() };
102106
this.loadedExtentsRtree_.insert(rect);
103107
}
104-
108+
105109
const fgb = deserialize((fgbStream && fgbStream.body) || this.url, rect);
106-
107-
let curLayer = L.geoJSON(null, this.options);
108-
curLayer.addTo(this);
110+
if (!this._validatedId) {
111+
this.curLayer = L.geoJSON(null, this.options);
112+
this.previousLayer && this.removeLayer(this.previousLayer);
113+
this.previousLayer = this.curLayer;
114+
this.curLayer.addTo(this);
115+
}
109116
for await (let feature of fgb) {
117+
if (this.strategy === 'bbox') {
118+
let id = feature.properties[this.idField];
119+
if (id && !this._validatedId) {
120+
this._validatedId = true;
121+
this._checked = true;
122+
}
123+
if (id && this._checked) {
124+
if (this._cacheIds.includes(id)) {
125+
continue;
126+
}
127+
this._cacheIds.push(id);
128+
}
129+
}
110130
if (this.options.featureLoader && typeof this.options.featureLoader === 'function') {
111131
feature = this.options.featureLoader(feature);
112132
}
113-
curLayer.addData(feature);
133+
this.curLayer.addData(feature);
114134
}
115-
this.previousLayer && this.removeLayer(this.previousLayer);
116-
this.previousLayer = curLayer;
117135
},
118136
async _getStream(url) {
119137
return await FetchRequest.get(url, {}, { withoutFormatSuffix: true }).then(function (response) {

src/leaflet/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"jsonsql": "0.2.5",
2525
"pbf": "3.2.1",
2626
"proj4": "2.9.0",
27-
"flatgeobuf": "3.23.1"
27+
"flatgeobuf": "3.23.1",
28+
"rbush": "^2.0.2"
2829
}
2930
}

src/mapboxgl/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@supermap/iclient-common": "11.1.0-beta",
2323
"canvg": "3.0.10",
2424
"xml-js": "1.6.11",
25-
"flatgeobuf": "3.23.1"
25+
"flatgeobuf": "3.23.1",
26+
"rbush": "^2.0.2"
2627
}
2728
}

src/openlayers/overlay/FGB.js

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import GeoJSON from 'ol/format/GeoJSON';
1414
* @classdesc FGB 图层源,该图层源把 {@link FlatGeobuf} 格式解析为点线面要素。
1515
* @version 11.1.0
1616
* @param {Object} opt_options - 参数。
17-
* @param {string} opt_options.url - FGB 服务地址,例如:http://localhost:8090/iserver/services/xxx/rest/data/featureResults/newResourceId.fgb。
18-
* @param {ol.loadingstrategy} [opt_options.strategy='bbox'] - 指定加载策略,可选值为 ol.loadingstrategy.all,ol/loadingstrategy.bbox。all为全部加载, bbox为当前可见范围加载
17+
* @param {string} opt_options.url - FGB 地址,例如:http://localhost:8090/iserver/services/xxx/rest/data/featureResults/newResourceId.fgb。
18+
* @param {ol.loadingstrategy} [opt_options.strategy= ol.loadingstrategy.bbox] - ol.loadingstrategy.all为全量加载,要素会以流的方式渲染到地图。 ol.loadingstrategy.bbox为当前可见范围加载,当地图范围改变时会重新加载要素,此时可以通过idField 参数来标识已被加载过的要素,被标识的要素无需再次加载。idField 参数无效时会清空要素,重新加载。
1919
* @param {Array} [opt_options.extent] - 加载范围, 参数规范为: [minX, minY, maxX, maxY], 传递此参数后, 图层将使用局部加载。
2020
* @param {function} [opt_options.featureLoader] - 要素加载回调函数
2121
* @param {boolean} [opt_options.overlaps] - 是否优化重叠要素的填充与描边操作
2222
* @param {boolean} [opt_options.useSpatialIndex] - 是否启用要素空间索引
2323
* @param {boolean} [opt_options.wrapX] - 是否平铺地图
24+
* @param {boolean} [opt_options.idField='SmID'] - 要素属性中表示唯一标识的字段,当 strategy 为 ol.loadingstrategy.bbox时生效。
2425
* @extends {ol.source.Vector}
2526
* @usage
2627
*/
@@ -29,15 +30,24 @@ export class FGB extends VectorSource {
2930
const baseOptions = Object.assign({ strategy: bbox }, options);
3031
delete baseOptions.url;
3132
delete baseOptions.extent;
33+
delete baseOptions.idField;
3234
super(baseOptions);
3335
this.options = options || {};
3436
this.strategy = baseOptions.strategy;
3537
this.url = this.options.url;
3638
this.extent = this.options.extent;
39+
this._idField = this.options.idField || 'SmID';
40+
this._validatedId = false;
41+
this._checked = false;
3742
this.setLoader(async function (extent) {
38-
if (this.extent && this.strategy === bbox) {
39-
const intersectExtent = getIntersection(this.extent, extent);
40-
extent = (intersectExtent && intersectExtent.length) ? intersectExtent : this.extent;
43+
if (this.strategy === bbox) {
44+
if (!this._validatedId) {
45+
this.clear();
46+
}
47+
if (this.extent) {
48+
const intersectExtent = getIntersection(this.extent, extent);
49+
extent = (intersectExtent && intersectExtent.length) ? intersectExtent : this.extent;
50+
}
4151
}
4252
if (!this.extent && (this.strategy === all || !isFinite(extent[0]))) {
4353
extent = [];
@@ -62,7 +72,15 @@ export class FGB extends VectorSource {
6272
}
6373
const fgb = deserialize(url, rect);
6474
for await (let feature of fgb) {
75+
let id = feature.properties[this._idField];
76+
if (id && !this._validatedId) {
77+
this._validatedId = true;
78+
this._checked = true;
79+
}
6580
feature = new GeoJSON().readFeature(feature);
81+
if (id && this._checked) {
82+
feature.setId(id);
83+
}
6684
if (this.options.featureLoader && typeof this.options.featureLoader === 'function') {
6785
feature = this.options.featureLoader(feature);
6886
}

src/openlayers/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"canvg": "3.0.10",
2525
"lodash.remove": "^4.7.0",
2626
"lodash.difference": "^4.5.0",
27-
"flatgeobuf": "3.23.1"
27+
"flatgeobuf": "3.23.1",
28+
"rbush": "^2.0.2"
2829
}
2930
}

0 commit comments

Comments
 (0)