Reputation: 705
I am using Mapbox GL JS to find out the nearest features to a clicked spot the user has clicked on the map. Its working great. But I'd like to output a approximate distance. The code Im using is below...
function nearestFeature(y,x) {
var bbox = [[y, x], [y, x]];
var featuresBuilding = map.queryRenderedFeatures(bbox, { layers: ['MyBuildingLayer'] });
if (featuresBuilding[0]) {
//found
}else{
//widen the area
for (i = 1;i<100;i++) {
bbox = [[y-i, x-i], [y+i, x+i]];
featuresBuilding = map.queryRenderedFeatures(bbox, { layers: ['MyBuildingLayer'] });
if (featuresBuilding[0]) {
//calculate distance
var distance = 100*i;
break;
}
}
}
}
I might be complicating this issue but essentially I need to work out the distance a point difference is for the X / Y and multiply the meter distance to get a rough estimation. I used var distance = 100*i to illustrate this, I need to work out how to acertain the dummy 100 figure...
Upvotes: 1
Views: 1809
Reputation: 2312
I once had a project where I also needed the value of 1px as a distance value to build something like a scale control (https://www.mapbox.com/mapbox-gl-js/api/#scalecontrol)
The solution is using the bounding box of the current viewport to calculate the distance between 2 points. Dividing this by the users viewport width will give you the distance for 1 pixel. I Used the mapbox scale control to check my values against theirs and the result seems to be reasonable.
I came up with this solution (requires turf.js). You can see the full working example on a quick jsfiddle I created: https://jsfiddle.net/andi_lo/38h7m5wx/
function getDistance() {
const bounds = map.getBounds();
const topLeft = turf.point([bounds._ne.lng, bounds._ne.lat]);
const topRight = turf.point([bounds._sw.lng, bounds._ne.lat]);
const bottomLeft = turf.point([bounds._ne.lng, bounds._sw.lat]);
const bottomRight = turf.point([bounds._sw.lng, bounds._sw.lat]);
const middleLeft = turf.midpoint(topLeft, bottomLeft);
const middleRight = turf.midpoint(topRight, bottomRight);
const distance = turf.distance(middleLeft, middleRight, 'kilometers');
return distance;
}
const clientWidth = window.innerWidth;
const distance = getDistance();
const onePixel = distance / clientWidth;
console.log(`1px is ~${onePixel.toFixed(3)} km or ${Math.ceil((onePixel) * 1000)} meters`);
Upvotes: 2