mapbox / mapbox-react-examples

Example patterns for building React apps with Mapbox GL JS
https://blog.mapbox.com/mapbox-gl-js-react-764da6cc074a
BSD 2-Clause "Simplified" License
619 stars 249 forks source link

In the markers custom example my markers are not accurate and move all over the screen #19

Closed wakywayne closed 1 year ago

wakywayne commented 2 years ago

I am using a fixed-sized map which I assume is the issue. Also worth notin I am in nextJs, but I don't think that is the issue. Are there any workarounds for this?

Here is my code

import mapboxgl from "mapbox-gl";
import React, { useEffect, useRef } from "react";
import ReactDOM from "react-dom";

// Im hideing my token but i am definitely using the right one

mapboxgl.accessToken = "token";

const geoJson = [
    {
        "type": "Feature",
        "properties": {
            "title": "Lincoln Park",
            "description": "A northside park that is home to the Lincoln Park Zoo"
        },
        "geometry": {
            "coordinates": [
                -87.637596,
                41.940403
            ],
            "type": "Point"
        }
    },
    {
        "type": "Feature",
        "properties": {
            "title": "Burnham Park",
            "description": "A lakefront park on Chicago's south side"
        },
        "geometry": {
            "coordinates": [
                -87.603735,
                41.829985
            ],
            "type": "Point"
        }
    },
    {
        "type": "Feature",
        "properties": {
            "title": "Millennium Park",
            "description": "A downtown park known for its art installations and unique architecture"
        },
        "geometry": {
            "coordinates": [
                -87.622554,
                41.882534
            ],
            "type": "Point"
        }
    },
]

const Marker = ({ onClick, children, feature }) => {
    const _onClick = () => {
        onClick(feature.properties.description);
    };

    return (
        <button onClick={_onClick} className="marker">
            {children}
        </button>
    );
};

const Map = () => {
    const mapContainerRef = useRef(null);

    // Initialize map when component mounts
    useEffect(() => {
        const map = new mapboxgl.Map({
            container: mapContainerRef.current,
            style: "mapbox://styles/mapbox/streets-v11",
            center: [-87.65, 41.84],
            zoom: 10,
        });

        // Render custom marker components
        geoJson.forEach((feature) => {
            // Create a React ref
            const ref = React.createRef();
            // Create a new DOM node and save it to the React ref
            ref.current = document.createElement("div");
            // Render a Marker Component on our new DOM node
            ReactDOM.render(
                <Marker onClick={markerClicked} feature={feature} />,
                ref.current
            );

            // Create a Mapbox Marker at our new DOM node
            new mapboxgl.Marker(ref.current)
                .setLngLat(feature.geometry.coordinates)
                .addTo(map);
        });

        // Add navigation control (the +/- zoom buttons)
        map.addControl(new mapboxgl.NavigationControl(), "top-right");

        // Clean up on unmount
        return () => map.remove();
    }, []);

    const markerClicked = (title) => {
        window.alert(title);
    };

    return (
        <div>
            <div className="map-container" ref={mapContainerRef} />
        </div>
    );
};

export default Map;

CSS

.map-container {
  height: 400px;
}

.sidebarStyle {
  display: inline-block;
  position: absolute;
  top: 0;
  left: 0;
  margin: 12px;
  background-color: #404040;
  color: #ffffff;
  z-index: 1 !important;
  padding: 6px;
  font-weight: bold;
}

.marker {
  background-color: #4CAF50;
  border: 1px solid blue;
  color: white;
  padding: 20px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  border-radius: 50%;
}
viktorrenkema commented 1 year ago

Ran into the same issue, this is happening because you're not loading Mapbox' css that's required to make those markers work well. Just add this import to your <head/>: <link href='https://api.tiles.mapbox.com/mapbox-gl-js/v2.9.2/mapbox-gl.css' rel='stylesheet' />

Or import it in some other way. Instantly fixed it for me. Found the 'answer' here: https://docs.mapbox.com/help/tutorials/custom-markers-gl-js/, and you'll also notice Mapbox logged an error with a not-quite-helpful link in the console that some css was still missing.