Skip to content

Commit

Permalink
fix: sharemap popup not displayed (#1904)
Browse files Browse the repository at this point in the history
* Fixed sharemap popup not displayed

* Fix for more layer kinds in urlParams.feature

---------

Co-authored-by: Stefan Forsgren <[email protected]>
  • Loading branch information
steff-o and Stefan Forsgren authored Nov 24, 2023
1 parent 110e18a commit fb574fe
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 47 deletions.
6 changes: 3 additions & 3 deletions src/featureinfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -601,8 +601,8 @@ const Featureinfo = function Featureinfo(options = {}) {
};

/**
* Shows the featureinfo popup/sidebar/infowindow for the provided feature and fit the view to it.
* @param {any} featureObj An object containing layerName and feature
* Shows the featureinfo popup/sidebar/infowindow for the provided features and fit the view to it.
* @param {any} featureObj An object containing layerName and feature. "feature" is either one Feature or an Array of Feature
* @param {any} opts An object containing options. Supported options are : coordinate, the coordinate where popup will be shown. If omitted first feature is used.
* ignorePan, do not autopan if type is overlay. Pan should be supressed if view is changed manually to avoid contradicting animations.
* @returns nothing
Expand All @@ -624,7 +624,7 @@ const Featureinfo = function Featureinfo(options = {}) {
}
if (newItems.length > 0) {
render(newItems, identifyTarget, opts.coordinate || maputils.getCenter(newItems[0].getFeature().getGeometry()), opts);
viewer.getMap().getView().fit(maputils.getExtent(featureObj.feature));
viewer.getMap().getView().fit(maputils.getExtent(newItems.map(i => i.getFeature())));
}
};

Expand Down
3 changes: 2 additions & 1 deletion src/layer/agsfeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function createSource({
const esrijsonFormat = new EsriJSON();
const vectorSource = new VectorSource({
attributions: attribution,
loader(extent, resolution, projection) {
loader(extent, resolution, projection, success) {
const that = this;
let url = sourceUrl.endsWith('/') ? sourceUrl : `${sourceUrl}/`;
url += id
Expand All @@ -40,6 +40,7 @@ function createSource({
if (features.length > 0) {
that.addFeatures(features);
}
success(features);
}).catch(error => console.warn(error));
},
strategy: loadingstrategy.bbox
Expand Down
3 changes: 2 additions & 1 deletion src/layer/geojson.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function createSource(options) {
if (options.url) {
const vectorSource = new VectorSource({
attributions: options.attribution,
loader() {
loader(extent, resolution, projection, success) {
fetch(options.url, { headers: options.headers }).then(response => response.json()).then((data) => {
if (data.features) {
vectorSource.addFeatures(vectorSource.getFormat().readFeatures(data, formatOptions));
Expand All @@ -34,6 +34,7 @@ function createSource(options) {
});
}
}
success(vectorSource.getFeatures());
}).catch(error => console.warn(error));
},
format: new GeoJSON()
Expand Down
4 changes: 4 additions & 0 deletions src/maputils.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ const maputils = {
}
return center;
},
/**
* Gets the union extent for an array of features
* @param {any} featureArray An array of features
*/
getExtent: function getCenter(featureArray) {
const featureExtent = featureArray[0].getGeometry().getExtent();
let i;
Expand Down
97 changes: 55 additions & 42 deletions src/viewer.js
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,26 @@ const Viewer = function Viewer(targetOption, options = {}) {
return urlParams;
};

/**
* Internal helper used when urlParams.feature is set and the popup should be displayed.
* @param {any} feature
* @param {any} layerName
*/
const displayFeatureInfo = function displayFeatureInfo(feature, layerName) {
if (feature) {
const fidsbylayer = {};
fidsbylayer[layerName] = [feature.getId()];
featureinfo.showInfo(fidsbylayer, { ignorePan: true });
if (!urlParams.zoom && !urlParams.center) {
map.getView().fit(feature.getGeometry(), {
maxZoom: getResolutions().length - 2,
padding: [15, 15, 40, 15],
duration: 1000
});
}
}
};

return Component({
onInit() {
this.render();
Expand Down Expand Up @@ -577,50 +597,43 @@ const Viewer = function Viewer(targetOption, options = {}) {
const layer = getLayer(layerName);
if (layer && layer.get('type') !== 'GROUP') {
const layerType = layer.get('type');
// FIXME: postrender event is only emitted if any features from a layer is actually drawn, which means there is no feature in the default extent,
// it will not be triggered until map is panned or zoomed where a feature exists.
layer.once('postrender', () => {
const clusterSource = layer.getSource().source;
// Assume that id is just the second part of the argumment and adjust it for special cases later.
let id = featureId.split('.')[1];
let feature;

if (layerType === 'WFS') {
// WFS uses the layername as a part of the featureId. Problem is that it what the server think is the name that matters.
// First we assume that the layername is actually correct, then take the special cases
let idLayerPart = layerName;
const layerId = layer.get('id');
if (layerId) {
// if layer explicitly has set the id it takes precedense over name
// layer name already have popped the namespace part, but id is untouched.
idLayerPart = layerId.split(':').pop();
} else if (layerName.includes('__')) {
// If using the __-notation to use same layer several times, we must only use the actual layer name
idLayerPart = layerName.split('__')[0];
}
// Build the correct WFS id
id = `${idLayerPart}.${id}`;
}
// FIXME: ensure that feature is loaded. If using bbox and feature is outside default extent it will not be found.
// Workaround is to have a default extent covering the entire map with the layer in visible range or use strategy all
if (clusterSource) {
feature = clusterSource.getFeatureById(id);
} else {
feature = layer.getSource().getFeatureById(id);
const layerSource = layer.getSource().source ? layer.getSource().source : layer.getSource();
// Assume that id is just the second part of the argumment and adjust it for special cases later.
let id = featureId.split('.')[1];

if (layerType === 'WFS') {
// WFS uses the layername as a part of the featureId. Problem is that it what the server think is the name that matters.
// First we assume that the layername is actually correct, then take the special cases
let idLayerPart = layerName;
const layerId = layer.get('id');
if (layerId) {
// if layer explicitly has set the id it takes precedense over name
// layer name already have popped the namespace part, but id is untouched.
idLayerPart = layerId.split(':').pop();
} else if (layerName.includes('__')) {
// If using the __-notation to use same layer several times, we must only use the actual layer name
idLayerPart = layerName.split('__')[0];
}
// Build the correct WFS id
id = `${idLayerPart}.${id}`;
}

if (feature) {
const obj = {};
obj.feature = feature;
obj.layerName = layerName;
featureinfo.showFeatureInfo(obj);
map.getView().fit(feature.getGeometry(), {
maxZoom: getResolutions().length - 2,
padding: [15, 15, 40, 15],
duration: 1000
});
}
});
// Some layer types may already have been loaded, e.g. GeoJson with static configured features. As features are loaded
// on creation it is impossible to listen to the featuresloadend event, but on the other hand the features will be ready already
// when we get here. It is highly unlikely that a remote source is finished already, but that would work as well.
if (layerSource.getFeatures().length > 0) {
displayFeatureInfo(layerSource.getFeatureById(id), layerName);
} else {
// Set up an eventhandler and wait for the source to finsish loading if there are no features yet.
// Important that the source actually emits this event.
layerSource.once('featuresloadend', () => {
// FIXME: ensure that feature is loaded. If using bbox and feature is outside default extent it will not be found.
// Workaround is to have a default extent covering the entire map with the layer in visible range or use strategy all
// Most likely it will work as sharemap links contains center and zoom so extent will be visible. Most sane people
// will only share maps where the selected feature is in view
displayFeatureInfo(layerSource.getFeatureById(id), layerName);
});
}
}
}

Expand Down

0 comments on commit fb574fe

Please sign in to comment.