reactjsmapboxreact-map-gldeck.gl

Markers on ReactMapBoxGl not working when deck GL layers are added


I have a codebase in which I'm using ReactMapGL to display a map with custom HTML markers. Everything was working fine until I introduced DeckGL layers into the mix. Now, the previous markers on the ReactMapGL map do not work anymore. The DeckGL layer is placed on top of the map, and it seems to be intercepting all the interactions, making the markers unresponsive.

I want the DeckGL layer to be placed below the markers of the ReactMapGL map. I don't want to change too much in the existing code because the marker logic is perfect and it renders custom HTML. Additionally, I prefer not to use DeckGL's IconLayer because it doesn't offer the flexibility I need for map interactions.

import React, { useState, useRef } from "react";
import ReactMapGL, { Marker, Source, Layer } from "react-map-gl";
import DeckGL from "@deck.gl/react";
import { TripsLayer } from "@deck.gl/geo-layers";
import { AmbientLight, PointLight, LightingEffect } from "@deck.gl/core";

const MAPBOX_ACCESS_TOKEN = 'your_mapbox_token';
const DATA_URL = {
  TRIPS: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/trips-v7.json',
};

const MyMap = ({ markers }) => {
  const [viewport, setViewport] = useState({
    latitude: 37.8,
    longitude: -122.4,
    zoom: 14,
  });

  const ambientLight = new AmbientLight({ color: [255, 255, 255], intensity: 1.0 });
  const pointLight = new PointLight({ color: [255, 255, 255], intensity: 2.0, position: [-74.05, 40.7, 8000] });
  const lightingEffect = new LightingEffect({ ambientLight, pointLight });

  const layers = [
    new TripsLayer({
      id: 'trips',
      data: DATA_URL.TRIPS,
      getPath: d => d.path,
      getTimestamps: d => d.timestamps,
      getColor: d => d.vendor === 0 ? [253, 128, 93] : [23, 184, 190],
      opacity: 0.3,
      widthMinPixels: 2,
      rounded: true,
      trailLength: 180,
      currentTime: Date.now(),
    }),
  ];

  return (
    <DeckGL
      initialViewState={viewport}
      controller={true}
      layers={layers}
      effects={[lightingEffect]}
      onViewStateChange={({ viewState }) => setViewport(viewState)}
    >
      <ReactMapGL
        {...viewport}
        width="100%"
        height="100%"
        mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN}
        onViewportChange={setViewport}
      >
        {markers.map(marker => (
          <Marker key={marker.id} latitude={marker.latitude} longitude={marker.longitude}>
            <div>{marker.name}</div>
          </Marker>
        ))}
        <Source id="my-data" type="geojson" data={myGeoJsonData}>
          <Layer {...layerStyle} />
        </Source>
      </ReactMapGL>
    </DeckGL>
  );
};

export default MyMap;

Things I tried

  1. Z-index I tried using Z-index to solve the problem, but it didn't work either, I tried putting it in a div and giving them a z-index, that didn't work either.

Solution

  • Anyone on this issue, looking for a fix in the latest version I found it, use a mapbox-overlay for the additional layers you add. So you probably are stuck, with having a deckGL parent and within it a mapbox. and somehow the mapbox layer comes on top. and you can't use the markers or anything that mapbox renders in that case, just remove the deckGl parent it a overlay child to the mapboxgl, this article will help you out a lot

    Life saver link

    and some snippets that'll help you

    function DeckGLOverlay(props: DeckProps) {
      const overlay = useControl<MapboxOverlay>(() => new MapboxOverlay(props));
      overlay.setProps(props);
      return null;
    }
    
    const layers = [
          new [Your layer type]({
            id: "trips",
            data: DATA_URL.TRIPS,
            getPath: (d) => d.path,
            // additional attributes of your layers. 
          }),
        ];
    
    <DeckGLOverlay layers={layers} />