How to Stop Markers Moving on Zoom in Mapbox GL JS

Viewed 167

I have tried previous answers with no success.

On initial load custom markers are in the correct position, though I do have to manually shift them to the right by 220px to achieve this. There is no zoom level set due to the fitBounds we use, described in the next paragraph.

On zooming in or out, the markers lose their position - their position is only correct for a certain zoom level. I am using a Turf.js bbox to calculate the bounding box we can use in the fitBounds function (though this is slightly out with me having to shift the markers to the right 220px).

In my _app.js (Next.js) I import the css

import 'mapbox-gl/dist/mapbox-gl.css'

function MyApp({ Component, pageProps }) {
    return <Component {...pageProps} />
}

export default MyApp

This is my Map component

import React, { useRef, useEffect } from 'react'
import mapboxgl from 'mapbox-gl'
import * as turf from '@turf/turf'

mapboxgl.accessToken = process.env.NEXT_PUBLIC_MAPBOX_TOKEN

export default function App() {
    const mapContainer = useRef(null)
    const map = useRef(null)

var geojson = {
    type: 'FeatureCollection',
    features: [
        {
            type: 'Feature',
            properties: { price: 399, beds: 2 },
            geometry: { type: 'Point', coordinates: [115.1848543, -8.721661] },
        },
        {
            type: 'Feature',
            properties: { price: 450, beds: 3 },
            geometry: { type: 'Point', coordinates: [115.1676773, -8.72259] },
        },
    ],
}

var bbox = turf.bbox(geojson)

useEffect(() => {
    if (map.current) return // initialize map only once
    map.current = new mapboxgl.Map({
        container: mapContainer.current,
        style: 'mapbox://styles/mapbox/streets-v11',
    })

    for (const marker of geojson.features) {
        // Create a DOM element for each marker.
        const el = document.createElement('div')

        //? WE USE ml-[220px] AS THE MARKERS APPEAR 220PX TO THE LEFT OF WHERE THEY SHOULD BE
        el.className =
            'flex items-center justify-center h-[30px] px-3 tracking-wide font-extrabold rounded-full bg-zinc-100 border border-zinc-300 shadow-md text-[14px] text-black ml-[220px]'
        el.innerText = '$' + marker.properties.price

        // Add markers to the map.
        new mapboxgl.Marker(el).setLngLat(marker.geometry.coordinates).addTo(map.current)
    }

    map.current.fitBounds(bbox, { padding: 100 })
})

return <div ref={mapContainer} className='w-full h-screen' />

An example can be found here

Any help would be very much appreciated.

1 Answers

On initial load custom markers are in the correct position, though I do have to manually shift them to the right by 220px to achieve this.

This doesn't make sense. If you have to move them 220px, they're clearly not in the right position. Presumably, the longitude of the point is wrong, and by offsetting it 220px it temporarily looks right - but as soon as the zoom changes, it will be wrong by a different amount.

You need to:

  • get the right lat/longs for your markers
  • make sure your marker images don't contain extra white space
  • set icon-anchor correctly for your image design
Related