btb84
btb84

Reputation: 241

Javascript latitude and longitude to pixel on custom map

I have a list of stores described by their coordinates (latitude, longitude) and I need to parse them on my custom world map as markers (with css absolute positioning). Google map and other libraries (jVector map and similar) are not a solution. I've found some formulas to convert the lat/lon to pixel left/right values to be used for the markers, but the conversion seems not accurate.

You can see a demo clicking here. The red bullet should be Rome, and the green one should be Rio de Janeiro as example. Both are not where they should be, and the "wrong offset" is not always the same from marker to marker (in other words: adding a translateX(-XXpx) won't fix all of them).

There is clearly something I'm missing, and I'm quite sure that I should setup the map image in some way that I don't know and don't understand. Does anyone can help?

Thanks in advance, here's the relevant code of the demo:

<div id="map" style="width: 800px;margin:100px;auto;position:relative;background-color:#dedede;">
    <img src="map.svg" style="width:100%;">
</div>
<script>
    var map = document.getElementById('map');
    var stores = [
        {
            "name": "Rome",
            "n": 10,
            "lat": 41.9097306,
            "lng": 12.2558141,
            "fill": "red"
        },
        {
            "name": "Rio di Janeiro",
            "n": 5,
            "lat": -22.9138851,
            "lng": -43.7261746,
            "fill": "green"
        }
    ];
    stores.forEach(element => {
        var pos = coordToPixel(element.lat,element.lng);
        var marker = document.createElement('div');
        marker.className = 'marker';
        marker.style.left = pos.x+'px';
        marker.style.top = pos.y+'px';
        marker.style.backgroundColor = element.fill;
        map.appendChild(marker);
    });
    function coordToPixel(lat,lng)
    {
        var MAP_WIDTH = 800,
            MAP_HEIGHT = 444
            ;
        var x = ((lng+180)*MAP_WIDTH/360),
            y = ((90-lat)*MAP_HEIGHT/180)
            ;
        return {x,y}
    }
</script>

Upvotes: 2

Views: 2352

Answers (2)

btb84
btb84

Reputation: 241

So, just for anyone struggling with this issue, the problem was that I just was ignoring how the map image should be sized and drawn. Using a valid mercator projection map fixed everything, here are some examples

thanks guys for helping me understanding that!

Upvotes: 0

tandrieu
tandrieu

Reputation: 127

Your points are inaccurate because your formula does not take into account that the earth is not a flat plane.

Assuming you are using the mercador projection (looks like it to me).

pseudo code from a detailed answer

latitude    = 41.9097306;
longitude   = 12.2558141;

mapWidth    = 800;
mapHeight   = 444;

// get x value
x = (longitude+180)*(mapWidth/360)

// convert from degrees to radians
latRad = latitude*PI/180;

// get y value
mercN = ln(tan((PI/4)+(latRad/2)));
y     = (mapHeight/2)-(mapWidth*mercN/(2*PI));

Upvotes: 2

Related Questions