Good morning, when I query overlapping features the popup shows only the data of the above feature. How can I change the popup to show data for all features queried at that point?
Example project posted here
Geojson: (The geojson contains the 3 geometries positioned in the same coordinate)
var json_overlapped_feature = {
"type":"FeatureCollection",
"name":"overlapped_feature",
"crs":{"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}},
"features":[
{"type":"Feature","properties":{"Nome":"GEOMETRIA1"},"geometry":{"type":"Point","coordinates":[13.006901604608238,43.843783667531724]}},
{"type":"Feature","properties":{"Nome":"GEOMETRIA2"},"geometry":{"type":"Point","coordinates":[13.006901604608238,43.843783667531724]}},
{"type":"Feature","properties":{"Nome":"GEOMETRIA3"},"geometry":{"type":"Point","coordinates":[13.006901604608238,43.843783667531724]}}
]}
Layer: (the layer is declared with .readFeatures
so the features should be present in the map)
var format_overlapped_feature = new ol.format.GeoJSON();
var features_overlapped_feature = format_overlapped_feature.readFeatures(json_overlapped_feature,
{dataProjection: 'EPSG:4326', featureProjection: 'EPSG:3004'});
var jsonSource_overlapped_feature = new ol.source.Vector({
});
jsonSource_overlapped_feature.addFeatures(features_overlapped_feature);
var lyr_overlapped_feature = new ol.layer.Vector({
declutter: true,
source:jsonSource_overlapped_feature,
style: style_overlapped_feature,
title: 'overlapped_feature<br />\
<a class="layerlegend"<br />\
<img src="styles/legend/overlapped_feature_0.png" /> GEOMETRIA1<br />\
<img src="styles/legend/overlapped_feature_1.png" /> GEOMETRIA2<br />\
<img src="styles/legend/overlapped_feature_2.png" /> GEOMETRIA3<br /></a>'
});
Popup: (the popup is configured to query features, but it only queries the top one)
var onSingleClick = function(evt) {
var pixel = map.getEventPixel(evt.originalEvent);
var coord = evt.coordinate;
var popupField;
var popupText = '<ul>';
map.forEachFeatureAtPixel(pixel, function(feature, layer) {
var currentFeature = feature;
var currentFeatureKeys = currentFeature.getKeys();
popupText += '<li><table>';
for (var i=0; i<currentFeatureKeys.length; i++) {
if (currentFeatureKeys[i] != 'geometry') {
popupField = '';
if (layer.get('fieldLabels')[currentFeatureKeys[i]] == "inline label") {
popupField += '<th>' + layer.get('fieldAliases')[currentFeatureKeys[i]] + ':</th><td>';
} else {
popupField += '<td colspan="2">';
}
if (layer.get('fieldImages')[currentFeatureKeys[i]] != "ExternalResource") {
popupField += (currentFeature.get(currentFeatureKeys[i]) != null ? autolinker.link(currentFeature.get(currentFeatureKeys[i]).toLocaleString()) + '</td>' : '');
} else {
popupField += (currentFeature.get(currentFeatureKeys[i]) != null ? '<img src="images/' + currentFeature.get(currentFeatureKeys[i]).replace(/[\\\/:]/g, '_').trim() + '" /></td>' : '');
}
popupText += '<tr>' + popupField + '</tr>';
}
}
popupText += '</table>';
});
// disable popup if no feature
if (popupText == '<ul>') {
popupText = '';
} else {
popupText += '</ul>';
}
// display popup
if (popupText) {
overlayPopup.setPosition(coord);
content.innerHTML = popupText;
container.style.display = 'block';
} else {
container.style.display = 'none';
closer.blur();
}
};
Result: (only the higher geometry is queried)
### UPDATE ###
By eliminating declutter:true
from layer, the 3 geometries become interrogable, however the labels overlap. How to display them non-overlapping? I insert the style
Style
var size = 0;
var placement = 'point';
function categories_overlapped_feature(feature, value, size, resolution, labelText,
labelFont, labelFill, bufferColor, bufferWidth,
placement) {
switch(value.toString()) {case 'GEOMETRIA1':
return [ new ol.style.Style({
image: new ol.style.Circle({radius: 4.0 + size,
stroke: new ol.style.Stroke({color: 'rgba(35,35,35,1.0)', lineDash: null, lineCap: 'butt', lineJoin: 'miter', width: 0}), fill: new ol.style.Fill({color: 'rgba(135,239,166,1.0)'})}),
text: createTextStyle(feature, resolution, labelText, labelFont,
labelFill, placement, bufferColor,
bufferWidth)
})];
break;
case 'GEOMETRIA2':
return [ new ol.style.Style({
image: new ol.style.Circle({radius: 4.0 + size,
stroke: new ol.style.Stroke({color: 'rgba(35,35,35,1.0)', lineDash: null, lineCap: 'butt', lineJoin: 'miter', width: 0}), fill: new ol.style.Fill({color: 'rgba(52,87,229,1.0)'})}),
text: createTextStyle(feature, resolution, labelText, labelFont,
labelFill, placement, bufferColor,
bufferWidth)
})];
break;
case 'GEOMETRIA3':
return [ new ol.style.Style({
image: new ol.style.Circle({radius: 4.0 + size,
stroke: new ol.style.Stroke({color: 'rgba(35,35,35,1.0)', lineDash: null, lineCap: 'butt', lineJoin: 'miter', width: 0}), fill: new ol.style.Fill({color: 'rgba(216,191,91,1.0)'})}),
text: createTextStyle(feature, resolution, labelText, labelFont,
labelFill, placement, bufferColor,
bufferWidth)
})];
break;}};
var style_overlapped_feature = function(feature, resolution){
var context = {
feature: feature,
variables: {}
};
var value = feature.get("Nome");
var labelText = "";
size = 0;
var labelFont = "10px, sans-serif";
var labelFill = "#000000";
var bufferColor = "";
var bufferWidth = 0;
var textAlign = "left";
var offsetX = 8;
var offsetY = 3;
var placement = 'point';
if (feature.get("numcivico") !== null) {
labelText = String(feature.get("Nome"));
}
var style = categories_overlapped_feature(feature, value, size, resolution, labelText,
labelFont, labelFill, bufferColor,
bufferWidth, placement);
return style;
};
Based on Mike's help in the comments I realized that I couldn't query all the features in the same place as the declutter: true
option in the layer made them disappear from the map.
Testing declutter: false
solves this problem however all the labels appear in cascade, if configured as visible.
This destroys the map and slows it down.
A possible solution comes from a recent fix made by openlayers 6.15.1 reported here however I can't apply it to my project.
I worked around the problem by configuring the style differently. Before it was like this:
var style = [ new ol.style.Style({
image: new ol.style.RegularShape({
radius: 4.0 + size,
points: 4,
stroke: new ol.style.Stroke({
color: 'rgba(128,17,25)',
lineDash: null,
lineCap: 'butt',
lineJoin: 'miter',
width: 1}),
fill: new ol.style.Fill({
color: 'rgba(219,30,42,0.5)'})
}),
text: createTextStyle(feature, resolution, labelText, labelFont,
labelFill, placement, bufferColor,
bufferWidth)
})];
Now it's like this:
var style = [ new ol.style.Style({
geometry: new ol.geom.Circle(feature.getGeometry().getCoordinates(), 3*resolution),
stroke: new ol.style.Stroke({
color: 'rgba(35,35,35)',
lineDash: null,
lineCap: 'butt',
lineJoin: 'miter',
width: 1}),
fill: new ol.style.Fill({color: 'rgba(227,26,28,0.5)'}),
text: createTextStyle(feature, resolution, labelText, labelFont,
labelFill, placement, bufferColor,
bufferWidth)
})];
The result is that the declutter is deactivated for the geometries, but remains active for the labels (in the case of completely overlapping labels, only one will be visible).
Result: