Skip to content

Commit 2a077dd

Browse files
committed
make the zoom attribute value of mapFeature as a native value, fix the ordering of g elements for zooming in/out and attribute changes
1 parent c41683d commit 2a077dd

File tree

3 files changed

+96
-67
lines changed

3 files changed

+96
-67
lines changed

src/map-feature.js

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -70,25 +70,25 @@ export class MapFeature extends HTMLElement {
7070
attributeChangedCallback(name, oldValue, newValue) {
7171
switch (name) {
7272
case 'zoom': {
73-
this.whenReady().then(() => {
74-
if (oldValue !== newValue) {
75-
let layer = this._layer,
76-
layerEl = layer._layerEl,
77-
mapmlvectors = layer._mapmlvectors;
78-
// if the vector layer only has static features, should update zoom bounds when zoom attribute is changed
79-
if (mapmlvectors?._staticFeature) {
80-
this._removeInFeatureList(oldValue);
81-
let native = this._getNativeZoomAndCS(layer._content);
82-
mapmlvectors.zoomBounds = M.getZoomBounds(
83-
layer._content,
84-
native.zoom
85-
);
73+
if (oldValue !== newValue && this._layer) {
74+
let layer = this._layer,
75+
zoom = newValue,
76+
mapmlvectors = layer._mapmlvectors;
77+
// if the vector layer only has static features, should update zoom bounds when zoom attribute is changed
78+
if (mapmlvectors._staticFeature) {
79+
this._removeInFeatureList(oldValue);
80+
if (zoom in mapmlvectors._features) {
81+
mapmlvectors._features[zoom].push(this._featureGroup);
82+
} else {
83+
mapmlvectors._features[zoom] = [this._featureGroup];
8684
}
87-
//this._removeFeature();
88-
//this._updateFeature();
89-
this._reRender();
85+
let native = this._getNativeZoomAndCS(layer._content);
86+
mapmlvectors.zoomBounds = M.getZoomBounds(
87+
layer._content,
88+
native.zoom
89+
);
9090
}
91-
});
91+
}
9292
break;
9393
}
9494
}
@@ -123,8 +123,7 @@ export class MapFeature extends HTMLElement {
123123
return;
124124
}
125125
// re-render feature if there is any observed change
126-
this._removeFeature();
127-
this._updateFeature();
126+
this._reRender();
128127
}
129128
});
130129
this._observer.observe(this, {
@@ -147,6 +146,7 @@ export class MapFeature extends HTMLElement {
147146
if (this._groupEl.isConnected) {
148147
let native = this._getNativeZoomAndCS(this._layer._content);
149148
let placeholder = document.createElement('span');
149+
let mapmlvectors = this._layer._mapmlvectors;
150150
this._groupEl.insertAdjacentElement('beforebegin', placeholder);
151151

152152
this._featureGroup._map.removeLayer(this._featureGroup);
@@ -155,6 +155,9 @@ export class MapFeature extends HTMLElement {
155155
.addData(this, native.cs, native.zoom)
156156
.addTo(this._map);
157157
placeholder.replaceWith(this._featureGroup.options.group);
158+
// TODO: getBounds() should dynamically update the layerBounds
159+
this._layer._setLayerElExtent();
160+
delete this._getFeatureExtent;
158161
}
159162
}
160163

@@ -199,32 +202,43 @@ export class MapFeature extends HTMLElement {
199202
? this.parentNode
200203
: this.parentNode.host;
201204

202-
// arrow function is not hoisted, define before use
203-
let _attachedToMap = (e) => {
204-
this._parentEl.whenReady().then(() => {
205-
let parentLayer =
206-
this._parentEl.nodeName.toUpperCase() === 'LAYER-'
207-
? this._parentEl
208-
: this._parentEl.parentElement || this._parentEl.parentNode.host;
209-
this._layer = parentLayer._layer;
210-
this._map = this._layer._map;
211-
// "synchronize" the event handlers between map-feature and <g>
212-
if (!this.querySelector('map-geometry')) return;
213-
if (!this._parentEl._layer._mapmlvectors) {
214-
// if vector layer has not yet created (i.e. the layer- is not yet rendered on the map / layer is empty)
215-
this._layer.once('add', this._setUpEvents, this);
216-
return;
217-
} else if (!this._featureGroup) {
218-
// if the map-feature el or its subtree is updated
219-
// this._featureGroup has been free in this._removeFeature()
220-
this._updateFeature();
221-
} else {
222-
this._setUpEvents();
205+
this._parentEl.whenReady().then(() => {
206+
let parentLayer =
207+
this._parentEl.nodeName.toUpperCase() === 'LAYER-'
208+
? this._parentEl
209+
: this._parentEl.parentElement || this._parentEl.parentNode.host;
210+
this._layer = parentLayer._layer;
211+
this._map = this._layer._map;
212+
let mapmlvectors = this._layer._mapmlvectors;
213+
// "synchronize" the event handlers between map-feature and <g>
214+
if (!this.querySelector('map-geometry')) return;
215+
if (!this._extentEl) {
216+
let native = this._getNativeZoomAndCS(this._layer._content);
217+
this._featureGroup = mapmlvectors.addData(this, native.cs, native.zoom);
218+
if (parentLayer.checked) {
219+
this._featureGroup.addTo(this._map);
223220
}
224-
});
225-
};
221+
mapmlvectors._layers[this._featureGroup._leaflet_id] =
222+
this._featureGroup;
223+
if (mapmlvectors._staticFeature && !this._extentEl) {
224+
// update zoom bounds of vector layer
225+
mapmlvectors.zoomBounds = M.getZoomBounds(
226+
this._layer._content,
227+
this._getNativeZoomAndCS(this._layer._content).zoom
228+
);
229+
// todo: dynamically update layer bounds of vector layer
230+
mapmlvectors.layerBounds = M.getBounds(this._layer._content);
231+
// update map's zoom limit
232+
this._map._addZoomLimit(mapmlvectors);
233+
L.extend(mapmlvectors.options, mapmlvectors.zoomBounds);
234+
}
235+
}
226236

227-
_attachedToMap();
237+
if (Object.keys(mapmlvectors._layers).length === 1) {
238+
this._layer._setLayerElExtent();
239+
}
240+
this._setUpEvents();
241+
});
228242
}
229243

230244
_updateFeature() {
@@ -246,7 +260,7 @@ export class MapFeature extends HTMLElement {
246260
// update layer bounds of vector layer
247261
mapmlvectors.layerBounds = M.getBounds(this._layer._content);
248262
// add feature layers to map
249-
mapmlvectors._resetFeatures();
263+
// mapmlvectors._resetFeatures();
250264
this._layer._setLayerElExtent();
251265
// update map's zoom limit
252266
this._map._addZoomLimit(mapmlvectors);

src/mapml/layers/FeatureLayer.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ export var FeatureLayer = L.FeatureGroup.extend({
7777
this._map.featureIndex.cleanIndex();
7878
},
7979

80+
removeLayer: function (featureGroupLayer) {
81+
L.FeatureGroup.prototype.removeLayer.call(this, featureGroupLayer);
82+
delete this._layers[featureGroupLayer._leaflet_id];
83+
},
84+
8085
getEvents: function () {
8186
if (this._staticFeature) {
8287
return {
@@ -164,21 +169,35 @@ export var FeatureLayer = L.FeatureGroup.extend({
164169
},
165170

166171
_resetFeatures: function () {
167-
this.clearLayers();
168172
// since features are removed and re-added by zoom level, need to clean the feature index before re-adding
169173
if (this._map) this._map.featureIndex.cleanIndex();
170174
let map = this._map || this.options._leafletLayer._map;
171175
if (this._features) {
172176
for (let zoom in this._features) {
173177
for (let k = 0; k < this._features[zoom].length; k++) {
174-
let feature = this._features[zoom][k],
175-
checkRender = feature._checkRender(
178+
let featureGroupLayer = this._features[zoom][k],
179+
checkRender = featureGroupLayer._checkRender(
176180
map.getZoom(),
177181
this.zoomBounds.minZoom,
178182
this.zoomBounds.maxZoom
179183
);
180-
if (checkRender) {
181-
this.addLayer(feature);
184+
if (!checkRender) {
185+
let placeholder = document.createElement('span');
186+
placeholder.id = featureGroupLayer._leaflet_id;
187+
featureGroupLayer.defaultOptions.group.insertAdjacentElement(
188+
'beforebegin',
189+
placeholder
190+
);
191+
// removing the rendering without removing the feature from the feature list
192+
this.removeLayer(featureGroupLayer);
193+
} else if (!map.hasLayer(featureGroupLayer)) {
194+
this.addLayer(featureGroupLayer);
195+
// update the layerbounds
196+
let placeholder =
197+
featureGroupLayer.defaultOptions.group.parentNode.querySelector(
198+
`span[id="${featureGroupLayer._leaflet_id}"]`
199+
);
200+
placeholder.replaceWith(featureGroupLayer.defaultOptions.group);
182201
}
183202
}
184203
}

test/e2e/core/mapFeature.test.js

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,35 +45,33 @@ test.describe('Playwright MapFeature Custom Element Tests', () => {
4545
let layer = map.querySelector('layer-'),
4646
mapFeature = layer.querySelector('map-feature');
4747
mapFeature.setAttribute('zoom', '4');
48+
mapFeature.zoomTo();
4849
});
4950
await page.waitForTimeout(200);
50-
label = await page.$eval(
51-
'body > map > div > div > div.leaflet-pane.leaflet-map-pane > div.leaflet-pane.leaflet-overlay-pane > div > div.mapml-vector-container > svg > g > g:nth-child(1)',
52-
(g) => g.getAttribute('aria-label')
51+
let mapZoom = await page.$eval('body > map', (map) =>
52+
map.getAttribute('zoom')
5353
);
5454
// expect the associated <g> el to re-render and re-attach to the map
55-
expect(label).toEqual('feature with table properties');
55+
expect(mapZoom).toEqual('4');
5656

5757
// change <map-coordinates>
5858
await page.reload();
5959
await page.waitForTimeout(500);
60-
label = await page.$eval(
61-
'body > map > div > div > div.leaflet-pane.leaflet-map-pane > div.leaflet-pane.leaflet-overlay-pane > div > div.mapml-vector-container > svg > g > g:nth-child(1)',
62-
(g) => g.getAttribute('aria-label')
63-
);
64-
expect(label).toEqual("feature, role='button'");
65-
await page.$eval('body > map', (map) => {
60+
let prevExtentBR = await page.$eval('body > map', (map) => {
61+
let layer = map.querySelector('layer-'),
62+
mapFeature = layer.querySelector('map-feature');
63+
return mapFeature.extent.bottomRight.pcrs;
64+
});
65+
66+
let newExtentBR = await page.$eval('body > map', (map) => {
6667
let layer = map.querySelector('layer-'),
6768
mapFeature = layer.querySelector('map-feature'),
6869
mapCoord = mapFeature.querySelector('map-coordinates');
69-
mapCoord.innerHTML = '12 11 12 11 12 12 11 12';
70+
mapCoord.innerHTML = '12 11 12 11 12 12 11 13';
71+
return mapFeature.extent.bottomRight.pcrs;
7072
});
71-
label = await page.$eval(
72-
'body > map > div > div > div.leaflet-pane.leaflet-map-pane > div.leaflet-pane.leaflet-overlay-pane > div > div.mapml-vector-container > svg > g > g:nth-child(1)',
73-
(g) => g.getAttribute('aria-label')
74-
);
7573
// expect the associated <g> el to re-render and re-attach to the map
76-
expect(label).toEqual('feature with table properties');
74+
expect(newExtentBR === prevExtentBR).toBe(false);
7775

7876
// remove <map-properties>
7977
await page.$eval('body > map', (map) => {
@@ -175,8 +173,6 @@ test.describe('Playwright MapFeature Custom Element Tests', () => {
175173
});
176174

177175
test('Default click method test', async () => {
178-
await page.pause();
179-
180176
// click method test
181177
// <map-feature> with role="button" should have popup opened after click
182178
const popup = await page.$eval('body > map', (map) => {

0 commit comments

Comments
 (0)