If you mentally visualize a digital map of your town, you might think about the intersections, buildings, landmarks, and parks. On a Mapbox map, each of these features are known as “features.” Well played, Mapbox. I had a theory I could figure out if a user stepped into a “park” by simply detecting the type of feature at the user’s coordinates. As it turns out, Mapbox has a function that does exactly that and it’s called queryRenderedFeatures. However, this function takes x and y points rather than coordinates. This makes a lot of sense if you think about it. The queryRenderedFeatures looks for features that are currently rendered in the view of the map and you’re either asking about a feature at a certain point of contained within a boundary of points. Now I didn’t find a straightforward way to convert between coordinates and pixels but I already had a Marker element that represented my user rendered and this element contains a _pos property that had the x and y point I needed.

let post = userMarker._pos let features = this.map.queryRenderedFeatures(

[pos.x, pos.y], {

filter: ['==', 'class', 'park']

}

) if (features.length != 0) {

// Park!

}

Now this is amazing but it comes with a huge caveat. The fidelity of returned features is highly dependent on the zoom or expanse of the currently rendered map. If I were to zoom out to the whole city of New Orleans, Mapbox may return some of the major parks but I would lose those smaller neighborhood gems which are present at a closer zoom. For this reason, I chose to set a minZoom of 16.

In addition to allowing users to step into parks on the Mapbox map, I wanted to double down on exploration encouragement by suggesting a nearby park they could visit. Mapbox does have a geolocation API which allows me to find points of interest that include a certain string, such as “park.” However, this was not giving me the results I needed. Enter Foursquare API.

You might remember Foursquare as that check in app from years back. Well all those check ins and places data we provided makes for one hell of a developer platform and Foursquare makes it available for free in non-commercial usages. Unbelievable. The endpoint we need is their Venue Search and after a bit of experimentation, I had it returning exactly what we needed. The `ll` value is that of our current user. Our `intent` is set to browse so it returns nearby results rather than popular results as that was our preference. The `radius` was to 10000 meters. Finally, I could the category id for parks on Foursquare’s incredible list of categories. Put it all together in a simple request, and you’ve got all the parks you need.



url: '

method: 'GET',

qs: {

client_id: 'YOUR_CLIENT_ID',

client_secret: 'YOUR_CLIENT_SECRET',

ll: `${latitude},${longitude}`,

categoryId: '4bf58dd8d48988d163941735',

v: '20181002',

limit: 10,

intent: 'browse',

radius: 10000

}

}, function(error, response, body) {

if (error) {

// do something

} else {

// parks!

}

}) request({url: ' https://api.foursquare.com/v2/venues/search ',method: 'GET',qs: {client_id: 'YOUR_CLIENT_ID',client_secret: 'YOUR_CLIENT_SECRET',ll: `${latitude},${longitude}`,categoryId: '4bf58dd8d48988d163941735',v: '20181002',limit: 10,intent: 'browse',radius: 10000}, function(error, response, body) {if (error) {// do something} else {// parks!})

Now that we have a park to direct the user to, I wanted to provide them walking directions so they knew how to get there. For this I jumped back to Mapbox and utilized their excellent Directions API. This involves providing the appropriate query parameters for their API call and then adding the supplied route to the map as a line.

Here’s the entire call:

fetch(`https://api.mapbox.com/directions/v5/mapbox/walking/${userLon},${userLat};${parkLon},${parkLat}?geometries=geojson&access_token=YOUR_ACCESS_TOKEN`)

.then(response => {

return response.json()

})

.then(data => {

let route = data.routes[0].geometry.coordinates map.addSource('route', {

'type': 'geojson',

'data': {

'type': 'Feature',

'geometry': {

'type': 'LineString',

'coordinates': route,

}

}

}) map.addLayer({

'id': 'route',

'type': 'line',

'source': 'route',

'paint': {

'line-color': '#65926B',

'line-width': 3

}

})

})

I like how the Foursquare and Mapbox platforms can come together to create this solution but I would love to see tighter integration between these two. I think the holy grail would be an API that would allow me to search for a point of interest and receive not only the location but it’s completely coordinate outline.

Of course, as I write this, Mapbox publishes this blog on a richer Foursquare integration. 😅 I’m going to look into whether or not this new integration will allow me to filter by parks. 🙏

Design