Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mapbox GL JS: zoom to filtered polygon?

I am using Mapbox GL JS to display a polygon layer. I would to allow the user to choose a name from a dropdown, and then highlight and zoom to the matching polygon.

I already know how to highlight the matching polygon using map.setFilter, but I don't know how to zoom to the bounds of the matching polygon. This is my current code:

map.addLayer({
    'id': 'polygon_hover',
    'source': 'mysource',
    'source-layer': 'mylayer',
    'type': 'fill',
    'paint': {
        'fill-color': 'red',
        "fill-opacity": 0.6
    },
    "filter": ["==", 'CUSTNAME', ""]
});
// Get details from dropdown
custname.on("change", function(e) {
    // get details of name from select event
    map.setFilter('polygon_hover', ["==", 'CUSTNAME', name]);
    // Get bounds of filtered polygon somehow?
    // var bounds = ??;
    // map.fitBounds(bounds);
});

I have examined the Mapbox example of zooming to bounds, but it assumes that you already know what the bounds are.

Is there any way it's possible to get the bounds of the polygon matching a map filter in Mapbox?

like image 588
Richard Avatar asked Mar 18 '17 17:03

Richard


3 Answers

I've the following code to fitBounds to Polygon center coords:

var coordinates = f.geometry.coordinates[0];
var bounds = coordinates.reduce(function (bounds, coord) {
    return bounds.extend(coord);
}, new mapboxgl.LngLatBounds(coordinates[0], coordinates[0]));

map.fitBounds(bounds, {
    padding: 20
});

Where f is one Feature.

like image 145
Nuno Ribeiro Avatar answered Nov 10 '22 02:11

Nuno Ribeiro


I found a solution to your problem. Leaflet has a polygon Class which takes an Array of polygon coordinates and has a function called getBounds() that returns south west and north east bounds. However, Leaflet doesn't follow the convention of LngLat, its format is LatLng. Therefore, you have to switch it. I took an example out from Mapbox Show drawn polygon area, and added exactly what you're looking for.

var polygon = data.features[0].geometry.coordinates;
var fit = new L.Polygon(polygon).getBounds();
var southWest = new mapboxgl.LngLat(fit['_southWest']['lat'], fit['_southWest']['lng']);
var northEast = new mapboxgl.LngLat(fit['_northEast']['lat'], fit['_northEast']['lng']);
var center = new mapboxgl.LngLatBounds(southWest, northEast).getCenter();
// map.flyTo({center: center, zoom: 10});
map.fitBounds(new mapboxgl.LngLatBounds(southWest, northEast));
like image 3
Luis Estevez Avatar answered Nov 10 '22 02:11

Luis Estevez


I see that the question is still relevant - I solved it making a separate request to the database containing all points of a given polygon and building bounds [[minLng, minLat], [maxLng, maxLat]]. All attempts to address geometry of already rendered or source features didn't work for me - most probably because Mapbox doesn't keep initial geoJSON in the tiles.

like image 2
Anna Avatar answered Nov 10 '22 02:11

Anna