Convert a Point (or PointLike) to LngLat object

Viewed 319

I have a mapbox map, and I want to add a fixed marker. With "fixed" I mean something that is in absolute so fixed respect of the map div container.

Example:

(0,0)         (200,0)
+-------------+
|             |
|             |
|             |
|      *      |
|             |
|             |
|             |
+-------------+
(0,300)       (200, 300)

In that case the marker * is at the center of the map so to place it I can use:

.marker {
  position: absolute;
  top: 50%;
  left: 50%
}

and then use getCenter():

const lngLatObj = map.getCenter()

but if I want the marker not in the center but for example at 20% left and 90% top?

(0,0)         (200,0)
+-------------+
|             |
|             |
|             |
|             |
|             |
|             |
| *           |
+-------------+
(0,300)       (200, 300)

Here you can see the map container and the marker * on that map.

suppose I have the pixel coordinates of *, how can I find the longitude and latitude of that point?

I imagine something like:

const x = 40
const y = 270
const point = new mapboxgl.Point(x, y)
const lngLat = point.??

I didn't have mouse or touch events. The point is fixed but user can zoom and pan the map.

With marker I mean not a mapbox Marker but a simple div element.

Thanks very much


here a reproducible example

2 Answers

If you know width and height in pixels and the pixel coordinates of the point you can calculate the corresponding lat/lng values based on the percentage wrt width/height and use these to offset the mapbox's LngLatBounds.

Depending on the desired precision a simple interpolation might do it:

var width = 200;
var height = 300;

var x = 40;
var y = 270;

var xPercentage = x / width;
var yPercentage = y / height;

var bounds = map.getBounds();

var long = bounds.getEast() + (xPercentage * (bounds.getEast() - bounds.getWest()));
var lat = bounds.getNorth() + (yPercentage * (bounds.getNorth() - bounds.getSouth()));

If you need more precision you must use spherical calculations, but the approach is the same.

I fix using geodesy:

const boundsNorth = new LatLon(bounds.getNorth(), bounds.getCenter().lng)
const boundsSouth = new LatLon(bounds.getSouth(), bounds.getCenter().lng)
const boundsEast = new LatLon(bounds.getCenter().lat, bounds.getEast())
const boundsWest = new LatLon(bounds.getCenter().lat, bounds.getWest())
const lat = boundsNorth.intermediatePointTo(boundsSouth, yPercentage).lat
const lng = boundsEast.intermediatePointTo(boundsWest, xPercentage).lng
Related