0

I have a Leaflet map with a button that turns overlays, and overlay opacity control, on and off. Overlays are loaded transparently, can have their opacity adjusted and then can be collectively be switched on or off.

It works well, but only if the first in the list of basemaps is selected for display. Selection of any other basemap correctly loads the overlays (see the attributions change) but does not show them. I've checked with multiple other layers and ordering, changed the one selected for initial display, and tried removing and re-adding the currently selected baselayer, but all without effect.

So I'm a bit baffled as to why it will only work with the first basemap in the list. How should I change it to work with whatever basemap is currently selected?

Leaflet Control Opacity plugin is at https://github.com/dayjournal/Leaflet.Control.Opacity

<html>
  <head>
    <title>Overlay test</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    <link
      href="https://unpkg.com/[email protected]/dist/leaflet.css"
      rel="stylesheet"
      integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A=="
      crossorigin=""
    />
    <script
      src="https://unpkg.com/[email protected]/dist/leaflet.js"
      integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA=="
      crossorigin=""
    ></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/L.Control.Opacity.min.js"></script>
    <link
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/L.Control.Opacity.min.css"
      rel="stylesheet"
    />

    <style type="text/css">
      #buttons {
        position: absolute;
        top: 0%;
        left: 5%;
        height: 5%;
      }
      #map {
        position: absolute;
        top: 5%;
        height: 90%;
        width: 100%;
      }
    </style>
  </head>

  <body>
    <div id="buttons"><button onclick="overlay_ctl()">overlays</button></div>
    <div id="map"></div>

    <script>
      const nls_param = {
        maxZoom: 18,
        useCache: true,
        crossOrigin: true,
        subdomains: "3",
      };
      var baseMaps = {
        osm: new L.tileLayer(
          "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
          {
            attribution:
              'Base map and data from OpenStreetMap and OpenStreetMap Foundation: &copy; <a href="https://www.openstreetmap.org/copyright" target="_blank">OpenStreetMap</a> contributors',
          }
        ),
        esri_world: new L.tileLayer(
          "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
          {
            attribution:
              "Tiles &copy; Esri &mdash; Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community",
          }
        ),
      };

      var overlayMaps = {
        OS_1900: new L.tileLayer(
          "https://geo.nls.uk/maps/os/1inch_2nd_ed/{z}/{x}/{y}.png",
          {
            opacity: 0.01,
            nls_param,
            attribution:
              'OS 1885-1900 from the <a href="http://maps.nls.uk/projects/api/ target="_blank"">NLS Maps API</a>',
          }
        ),
        OS_1920s: new L.tileLayer(
          "https://geo.nls.uk/maps/api/nls/{z}/{x}/{y}.jpg",
          {
            opacity: 0.01,
            nls_param,
            attribution:
              'OS 1920s from the <a href="http://maps.nls.uk/projects/api/ target="_blank"">NLS Maps API</a>',
          }
        ),
      };

      const map = L.map("map", {
        center: [51, 0],
        zoom: 7,
        zoomControl: false,
        layers: [baseMaps.esri_world],
      });

      L.control.layers(baseMaps).addTo(map);

      var octl; // overlay controller
      olay = L.control.opacity(overlayMaps, {
        collapsed: false,
        label: "Historic",
      });

      function overlay_ctl() {
        if (octl !== "show") {
          show_overlay();
        } else {
          lose_overlay();
        }
      }

      function show_overlay() {
        overlayMaps.OS_1900.addTo(map);
        overlayMaps.OS_1920s.addTo(map);
        olay.addTo(map);
        octl = "show";
      }
      function lose_overlay() {
        overlayMaps.OS_1900.removeFrom(map);
        overlayMaps.OS_1920s.removeFrom(map);
        olay.remove();
        octl = "hide";
      }
    </script>
  </body>
</html>

4
  • L.control.opacity is not part of vanilla Leaflet, but a plugin. You should have mentioned that and provided link to the plugin site.
    – TomazicM
    Apr 10, 2021 at 9:30
  • @TomazicM apologies; edited.
    – perplexed
    Apr 10, 2021 at 9:56
  • Since none of the TileLayers have a explicit z-index (inside the stacking context of the map pane), the TileLayer that was added to the map the last is shown on top. Also, you seem to want to use spread syntax on nls_params. Apr 10, 2021 at 14:29
  • Perfect, thankyou. The addition of layer.bringToBack() means it now works exactly as I'd hoped.
    – perplexed
    Apr 10, 2021 at 20:39

0