jonsken
jonsken

Reputation: 115

Leaflet: Change color onClick

I am trying to change the color of my GeoJSON-Layer on every click in my Ionic React App, but I only managed to change it once for the first click... My idea was to change the color between blue and red everytime a feature is clicked. I had the idea to check for the color in the options of the GeoJSON-Layer, but as written, it only changes the color once for the first click and afterwards nothing happens on any other click.

function LeafletMap() {
  const [map, setMap] = useState(null)

  const onEachClick = (info, layer) => {
    const part = info.properties.Objekt_ID
    const id = info.properties.FID_

    layer.bindPopup("Object ID: <b>" + part + "</b><br>FID: <b>" + id + "</b>")

    if(layer.options.color != "blue") {
      layer.on({
        click: (event) => {
          event.target.setStyle({
            color: "blue",
          });
        }
      }) 
    } else {
      layer.on({
        click: (event) => {
          event.target.setStyle({
            color: "red",
          });
        }
      }) 
    }
  }

  const displayMap = useMemo(
    () => (
      <MapContainer
        center={center}
        zoom={zoom}
        scrollWheelZoom={false}
        whenCreated={setMap}>
        <LayersControl position="topright">
          <LayersControl.BaseLayer checked name="OpenStreetMap - Map">
            <TileLayer
              attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
              url="https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png"
            />
          </LayersControl.BaseLayer>
          <LayersControl.BaseLayer name="Esri - Satelite">
            <TileLayer
              attribution='Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community'
              url="https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
            />
          </LayersControl.BaseLayer>
        </LayersControl>

        <GeoJSON data={PL.features} onEachFeature={onEachClick} color="blue"/>
        <GeoJSON data={WWD.features} onEachFeature={onEachClick} color="blue"/>
      </MapContainer>
    ),
    [],
  )

  window.dispatchEvent(new Event('resize'));

  return (
    <div>
      {displayMap}
    </div>
  )

}
export default LeafletMap

Upvotes: 0

Views: 2497

Answers (1)

kboul
kboul

Reputation: 14570

There is a really much simpler way to achieve the desired behavior. I can give an example using one geojson and then you can adjust it to your needs.

You need to reset geojson style after each layer click. You can achieve that by taking a geojson reference using react ref and leaflet's resetStyle method. And regarding the change of the style you only need to set the color after each click. No need for if statements there.

const geoJsonRef = useRef();

  const onEachClick = (feature, layer) => {
    const name = feature.properties.name;
    const density = feature.properties.density;

    layer.bindPopup(
      "Name: <b>" + name + "</b><br>Density: <b>" + density + "</b>"
    );

    layer.on({ click: handleFeatureClick });
  };

  const handleFeatureClick = (e) => {
    if (!geoJsonRef.current) return;
    geoJsonRef.current.resetStyle();

    const layer = e.target;

    layer.setStyle({ color: "red" });
  };

...
<GeoJSON ref={geoJsonRef} />

Here is a demo with some data taken from leaflet website

Upvotes: 2

Related Questions