1

I have the following code meant for Leaflet:

      const TileLayerNOAA = L.TileLayer.extend({
  getTileUrl(coords) {
    var z = coords.z -2;
    if (z<0) z=0;
    return 'https://gis.charttools.noaa.gov/arcgis/rest/services/MarineChart_Services/NOAACharts/MapServer/WMTS/tile/1.0.0/MarineChart_Services_NOAACharts/default/GoogleMapsCompatible/'+(coords.z-2)+'/'+coords.y+'/'+coords.x+'.png';
  }
});

  var charts = new TileLayerNOAA(curl, {
    attribution: 'NOAA Marine Charts',
    maxZoom: 17,
    tms: false,
    opacity: .4
  })

I have the following currently:

 const TileLayerNOAA = ({ coords, chartsEnabled, setChartsEnabled, ...props }) => {
    const adjustedZoom = Math.max(0, coords.z - 2);
    const url = `https://gis.charttools.noaa.gov/arcgis/rest/services/MarineChart_Services/NOAACharts/MapServer/WMTS/tile/1.0.0/MarineChart_Services_NOAACharts/default/GoogleMapsCompatible/${adjustedZoom}/${coords.y}/${coords.x}.png`;
  
    return (
      <TileLayer
        url={url}
        attribution="NOAA Marine Charts"
        maxZoom={17}
        tms={false}
        opacity={0.4}
        checked={chartsEnabled}
        onLoad={() => setChartsEnabled(true)}
        {...props}
      />
    );
  };



  const overlayMaps = {
    "NOAA Charts": (
      <TileLayerNOAA
      chartsEnabled={chartsEnabled}
      setChartsEnabled={() => setChartsEnabled(true)}
    />
    )
  };

In my return statement I have:

    <LayersControl position="bottomright">
          {Object.entries(baseMaps).map(([name, layer]) => (
            <BaseLayer key={name} checked={name === 'Satellite'} name={name}>
              <TileLayer url={layer._url} attribution={layer.options.attribution} {...layer.options} />
            </BaseLayer>
          ))}
          {Object.entries(overlayMaps).map(([name, layer]) => (
            <Overlay key={name} checked={false} name={name}>
  {layer}
</Overlay>
          ))}
        </LayersControl>

The tricky part is grabbing the z and subtracting 2 for each url or setting it 0 if z is negative. The current Leaflet for React code does not work currently. Gives an uncaught runtime error: Cannot read properties of undefined (reading 'z') TypeError: Cannot read properties of undefined (reading 'z')

If I hardcode the url to the following, it works but goes away after I zoom in or out so the url is confirmed to work:

const url = `https://gis.charttools.noaa.gov/arcgis/rest/services/MarineChart_Services/NOAACharts/MapServer/WMTS/tile/1.0.0/MarineChart_Services_NOAACharts/default/GoogleMapsCompatible/11/{y}/{x}.png`; 

1 Answer 1

1

Was able to get it with:

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

const TileLayerNOAA = ({ chartsEnabled, setChartsEnabled, ...props }) => {
  const [adjustedZoom, setAdjustedZoom] = useState(0);
  const map = useMap();

  useEffect(() => {
    const updateZoom = () => {
      const currentZoom = map.getZoom();
      setAdjustedZoom(Math.max(0, currentZoom - 2));
    };

    // Attach the zoom update function to the Leaflet map's zoomend event
    map.addEventListener('zoomend', updateZoom);

    // Initial update
    updateZoom();

    // Cleanup function to remove the event listener when the component unmounts
    return () => {
      map.removeEventListener('zoomend', updateZoom);
    };
  }, [map]);

  const url = `https://gis.charttools.noaa.gov/arcgis/rest/services/MarineChart_Services/NOAACharts/MapServer/WMTS/tile/1.0.0/MarineChart_Services_NOAACharts/default/GoogleMapsCompatible/${adjustedZoom}/{y}/{x}.png`;

  return (
    <TileLayer
      url={url}
      attribution="NOAA Marine Charts"
      maxZoom={17}
      tms={false}
      opacity={0.4}
      checked={chartsEnabled}
      onLoad={() => setChartsEnabled(true)}
      {...props}
    />
  );
};

export default TileLayerNOAA;

Basically you need to use mapRef to access zoom in react-leaflet

Not the answer you're looking for? Browse other questions tagged or ask your own question.