Reputation: 103
I followed this tutorial "Filter features within map view" and managed to adapt it to my data, which are polygons instead of points.
However, the popups on the side menu are not displayed, when I place the mouse over one of the locations, the popup does not appear on the map indicating the location as it should. The problem I believe is that because it is a polygon and not a point (a pair of coordinates) the code cannot display the location, the error in the console is:
"Uncaught Error:` LngLatLike` argument must be specified as a LngLat instance, an object {lng: <lng>, lat: <lat>}, an object {lon: <lng>, lat: <lat>}, or an array of [<lng>, <lat>] "
In the map popup I changed it from ".setLngLat (feature.geometry.coordinates)
"
to ".setLngLat (e.lngLat)
" and it worked, but not in the popup on the side menu.
I'm still starting to learn javascript and I couldn't find a solution, I thought about extracting the centroid from the polygon, but I don't know how to do it.
the code that generates the popup:
var prop = feature.properties;
var item = document.createElement('a');
item.href = prop.wikipedia;
item.target = '_blank';
item.textContent = prop.NM_UF + ' (' + prop.SIGLA_UF + ')';
item.addEventListener('mouseover', function () {
// Highlight corresponding feature on the map
popup
.setLngLat(feature.geometry.coordinates)
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
});
listingEl.appendChild(item);
});
Here is a codepen like the code: https://codepen.io/hugonbgg/pen/PoNwWVj and the debug: https://codepen.io/hugonbgg/debug/PoNwWVj/
Upvotes: 0
Views: 1256
Reputation: 3780
Long story short, you are using a source that includes Polygon
and MultiPolygon
features together, so your selected feature coordinates is sometimes an array and sometimes a multidimensional array.
There are different ways to solve this...
Quick and dirty
popup
.setLngLat(feature.geometry.coordinates[0][0]) //just add [0][0]
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
This just works but positions the popup tip on the first point of the first polygon... not definitely the best but it works.
The second method is what I would do...
Find the center of any feature through a method
I have created this codepen based on yours with this change to include a getFeatureCenter
method.
function getFeatureCenter(feature) {
let center = [];
let latitude = 0;
let longitude = 0;
let height = 0;
let coordinates = [];
feature.geometry.coordinates.forEach(function (c) {
let dupe = [];
if (feature.geometry.type === "MultiPolygon")
dupe.push(...c[0]); //deep clone to avoid modifying the original array
else
dupe.push(...c); //deep clone to avoid modifying the original array
dupe.splice(-1, 1); //features in mapbox repeat the first coordinates at the end. We remove it.
coordinates = coordinates.concat(dupe);
});
if (feature.geometry.type === "Point") {
center = coordinates[0];
}
else {
coordinates.forEach(function (c) {
latitude += c[0];
longitude += c[1];
});
center = [latitude / coordinates.length, longitude / coordinates.length];
}
return center;
}
and then change in your call to the popup
popup
.setLngLat(getFeatureCenter(feature)) //call the new method and enjoy!
.setText(
feature.properties.NM_UF +
' (' +
feature.properties.SIGLA_UF +
')'
)
.addTo(map);
This will find the feature center independently if it is Point
, Polygon
or MultiPolygon
...
PS.- If this answer solves your question, please mark it as "answer accepted", in that way will also help other users to know it was the right solution.
Upvotes: 1