MapBox GL JS marker offset
Asked Answered
A

4

11

I'm using MapBox GL JS to create a map with a custom marker:

var marker = new mapboxgl.Marker(container)
    .setLngLat([
        datacenters[country][city].coordinates.lng,
        datacenters[country][city].coordinates.lat
    ])
    .addTo(map);

However, I seem to have some kind of offset problem with the marker. The thing is: when zoomed out a bit, the bottom of the marker is not really pointing to the exact location:

Marker when zoomed out a bit

When I'm zooming in a bit further it reaches its destination and it's pointing to the exact spot.

Marker when zoomed in

I really love MapBox GL, but this particular problem is bugging me and I'd love to know how to solve it. When this is fixed my implementation is far more superior to the original mapping software I was using.

Accounting answered 4/8, 2016 at 13:9 Comment(1)
Out of interest, @egidius, are you planning on clustering these markers, and if you've done it, could you let me know how?Allegorist
K
17

From Mapbox GL JS 0.22.0 you're able to set an offset option to the marker. https://www.mapbox.com/mapbox-gl-js/api/#Marker

For example to offset the marker so that it's anchor is the middle bottom (for your pin marker) you would use:

var marker = new mapboxgl.Marker(container, {
        offset: [-width / 2, -height]
    })
    .setLngLat([
        datacenters[country][city].coordinates.lng,
        datacenters[country][city].coordinates.lat
    ])
    .addTo(map);
Kenwood answered 11/8, 2016 at 0:43 Comment(9)
Cool! I was using v0.21.0, so I guess my hack is still legit given my circumstances. Thank you so much. I'll just have to wait for v 0.22.0 to be released.Accounting
@Egidius It's now released github.com/mapbox/mapbox-gl-js/blob/master/CHANGELOG.mdKenwood
Awesome!! Never have had to wait this short amount of time for a releaseAccounting
I take it the 'width' and 'height' are the width and height in px of the marker you're using? @Kenwood Still struggling to get this to work! Even with the correct offset it remains inaccurate on zooming in and out...Allegorist
Finally got it.... it turns out my width needed to be negative width / 2 and the height to be height * 2...Allegorist
@HuwDavies The API description says "The offset in pixels as a PointLike object to apply relative to the element's top left corner. Negatives indicate left and up." Based on that I would have thought it would be [-width/2, -height]?Kenwood
@Kenwood strangely enough the height isn't negative. It's double. I guess people will have to experiment with their markers ;)Allegorist
Mine works when I do negative width/2 and negative heightAnabas
In the current version, the offset is relative to the center of the marker, not the top left: docs.mapbox.com/mapbox-gl-js/api/#pointlikeToadstool
T
9

New solution for mapbox-gl.js v1.0.0 - Marker objects now have an anchor option to set the position to align to the marker's Lat/Lng: https://docs.mapbox.com/mapbox-gl-js/api/#marker

var marker = new mapboxgl.Marker(container, {anchor: 'bottom');

This should cover most cases and is more reliable than a pixel offset in my experience.

Toadstool answered 27/5, 2019 at 9:49 Comment(1)
This worked for me, using a similar marker to the questioner, without having to set an offset.Eustis
A
2

I've found an solution to my problem. It might be somewhat hacky, but it solves the positioning problem of the marker: I'm using a Popup fill it with a font awesome map marker icon and remove it's "tooltip styled" borders:

Javascript:

map.on('load', function() {
    var container = document.createElement('div');
    var icon = document.createElement('i');
    icon.dataset.city = city;

    icon.addEventListener('click', function(e) {
        var city = e.target.dataset.city;
        var country = e.target.dataset.country
        flyTo(datacenters[country][city].coordinates);
    });

    icon.classList.add('fa', 'fa-map-marker', 'fa-2x');
    container.appendChild(icon);

    var popup = new mapboxgl.Popup({
            closeButton: false,
            closeOnClick: false
        })
        .setLngLat([
            datacenters[country][city].coordinates.lng,
            datacenters[country][city].coordinates.lat
        ])
        .setDOMContent(container)
        .addTo(map);
});

CSS:

.map div.mapboxgl-popup-content {
    background: none;
    padding: 0;
}

.map .mapboxgl-popup-tip {
    display: none;
}

I just hope someone comes up with a real solution, because this feels kinda dirty to me. But hey: it does the job just fine!

Accounting answered 4/8, 2016 at 13:48 Comment(0)
G
2

Mapbox Marker now has an element option see this link Mapbox Marker. So instead of appending the icon HTML to the Div element you can simply add into the options when creating a marker. I found this also gets rid of the offset problem. So using the code above you can do this....

var icon = document.createElement('i');
icon.classList.add('fas', 'fa-map-marker-alt');
icon.style.color = 'blue';
new mapboxgl.Marker(container, {anchor: 'center', offset: [0, 0], element: icon})

Also the CSS for the marker can be updated to allow a pointer

.mapboxgl-marker {
    border: none;
    cursor: pointer;
}
Gyrostatics answered 27/11, 2020 at 11:44 Comment(1)
Thanks for the offset: [0, 0] hint, that resolved the problem for me.Somersomers

© 2022 - 2024 — McMap. All rights reserved.