PauCasademont
PauCasademont

Reputation: 287

React Leaflet display legend using MapContainer

I'm using React leaflet 3.1.0 and I want to display a legend in the map. I built a component for the legend and pass map instance that I get from MapContainer whenCreated({setMap}).

Map Component:

import { useState } from 'react';
import { MapContainer, TileLayer } from 'react-leaflet';

import './Map.css';
import Legend from './Legend/Legend';

const INITIAL_MAP_CONFIG = {center: [41.98311,2.82493], zoom: 14}

function Map() {
    const [map, setMap] = useState(null);
   
    return (
        <MapContainer center={INITIAL_MAP_CONFIG.center} zoom={INITIAL_MAP_CONFIG.zoom} scrollWheelZoom={true} whenCreated={setMap}>
            <TileLayer
                attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
                url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
            />              
            <Legend map={map} /> 
        </MapContainer>  
    )
}

export default Map

Legend Component:

import { useEffect } from 'react';
import L from 'leaflet';

function Legend({ map }) {    
    
    useEffect(() => {
        if (map){
            const legend = L.control({ position: "bottomright" });
    
            legend.onAdd = () => {
                const div = L.DomUtil.create('div', 'info legend');
                div.innerHTML = 
                     '<h4>This is the legend</h4>' + 
                     '<b>Lorem ipsum dolor sit amet consectetur adipiscing</b>';
                return div;
            }
    
            legend.addTo(map);
        }
    },[]);
    return null
}

export default Legend

Map CSS:

.leaflet-container {
     width: 100vw;
     height: 100vh;
}

Legend CSS:

.info {
    padding: 6px 8px;
    font: 14px/16px Arial, Helvetica, sans-serif;
    background: white;
    border-radius: 5px;
}

.legend {
    text-align: left;
    line-height: 18px;
    color: #555;
}

I don't get any errors but the legend can not be seen.

Upvotes: 4

Views: 5012

Answers (2)

Dragos UniqQum
Dragos UniqQum

Reputation: 665

If you want to createa a custom LEGEND , just add z-index big enough to the legend's container element.

export const Legend = styled.div`
      border-top-left-radius: 10px;
      position: absolute;
      width: 160px;
      height: 120px;
      background-color: rgba(255, 255, 255, 0.8);
      bottom: 0;
      right: 0;
      z-index: 1000;
      display: grid;
      grid-template-columns: 1fr;
      padding: 1%;
    `;

  <MapContainer
      center={CENTER}
      zoom={10}
      scrollWheelZoom={true}
      style={{ width: "100%", height: 500 }}
      ref={mapRef}
    >
.....
           <Legend>
                {LegendImages.map((legend) => {
                  return (
                    <LegendElement>
                      <img
                        src={legend.src}
                        style={{ width: 30, height: 30 }}
                      />
                      <LegendText>{legend.label}</LegendText>
                    </LegendElement>
                  );
                })}
              </Legend>
    </MapContainer>

Upvotes: 0

kboul
kboul

Reputation: 14570

Try placing the map instances in the dependency arrray. In the first render map is null therefore the legend cannot be added to the map.

function Legend({ map }) {
  console.log(map);
  useEffect(() => {
    if (map) {
      const legend = L.control({ position: "bottomright" });

      legend.onAdd = () => {
        const div = L.DomUtil.create("div", "info legend");
        div.innerHTML =
          "<h4>This is the legend</h4>" +
          "<b>Lorem ipsum dolor sit amet consectetur adipiscing</b>";
        return div;
      };

      legend.addTo(map);
    }
  }, [map]); //here add map
  return null;
}

Demo

Upvotes: 4

Related Questions