3

I am trying to create a code using leaflet and am having trouble animating a series of weather radar images using WMS. My code is as follows:

<!DOCTYPE html>

<html>

<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.css" />

    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.js">

    </script>

    <div id="map" style='width: 943px; height: 480px;'></div>

    <link rel="stylesheet" href="https://cdn.rawgit.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.control.min.css"
    />

</head>

<body>

    <script type="text/javascript" src="https://cdn.rawgit.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.min.js">

    </script>

    <script type="text/javascript" src="https://cdn.rawgit.com/nezasa/iso8601-js-period/master/iso8601.min.js">

    </script>

    <script>
        //make the map

      var wmsLayerRadarRrai4kmLink = 'https://geo.weather.gc.ca/geomet?'

      var wmsLayerRadarRrai4km = L.tileLayer.wms(wmsLayerRadarRrai4kmLink, {
        layers: 'RADAR_RRAI',
        version: '1.1.0',
        format: 'image/png',
        transparent: true
        //opacity: .75
      });

      var wmsLayerRadarRrai4kmTD = L.timeDimension.layer.wms(wmsLayerRadarRrai4km, {
      });

      var map = L.map('map', {
        center: [49.9, -97.215],
        zoom: 5,
        fullScreenControl: true,
        timeDimension: true,
        timeDimensionControl: true,
        timeDimensionOptions: {
        },
        timeDimensionControlOptions: {
          autoPlay: true, 
          playerOptions: {
          loop: true,
          timeSteps: 1,
          }
        }
      });

      //get the wms layers



      var proxy = 'server/proxy.php'



      //group wms layers

      var overlayMaps = {
        "Radar Rain 4km": wmsLayerRadarRrai4kmTD
      };

    //get basemaps using tileLayer

      var basemapDark =  L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}  {r}.png', {
          attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy;<a href="https://carto.com/attributions">CARTO</a>',
          subdomains: 'abcd',
        maxZoom: 19
      });

      var basemapLight = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          maxZoom: 19,
          attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
      });

      //group basemaps

      var baseMaps = {
        "Light": basemapLight,
        "Dark": basemapDark
      };

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

      L.control.timeDimension
    </script>
</body>

</html>

The initial default layer will load, but once the time layer is enables/played, nothing else displays. It appears to be grabbing the correct time component from the GetCapabilities, so I am not sure what the issue is.

4

It looks like like Leaflet TimeDimension plugin and https://geo.weather.gc.ca/geomet WMS service do not go very well along together.

TimeDimension plugin uses getCapabilities call to get time series from WMS service. Response has hefty 14MB. Plugin analyzes this response to get times for time series calls to WMS service (time parameter).

Obviously something goes wrong in this analysis. I checked time series calls in debugger and all return status 500 - Internal server error. Example of one such call:

https://geo.weather.gc.ca/geomet?&service=WMS&request=GetMap&layers=RADAR_RRAI&styles=&format=image%2Fpng&transparent=true&version=1.1.0&time=2019-05-07T14%3A20%3A00.000Z&width=256&height=256&srs=EPSG%3A3857&bbox=-11271098.44281895,6261721.357121641,-10018754.171394622,7514065.628545967

Time in this call is 2019-05-07T14:20:00.000Z.

I checked getCapabilities response and chosen one of the times I found there. Time was 2019-05-07T17:00:00Z. With this time I got valid response.

EDIT: Some further research showed that the only problem is in time format passed to WMS service. TimeDimension plugin uses ISO-8601 format YYYY-MM-DDTHH:mm:ss.sssZ, but WMS service expects time without hundreds of seconds YYYY-MM-DDTHH:mm:ssZ.

Since TimeDimension plugin offers no option or method to format time, the only solution is to override method _createLayerForTime of L.TimeDimension.Layer.WMS object, which prepares WMS request:

L.TimeDimension.Layer.WMS.include({
  _createLayerForTime: function(time){
      var wmsParams = this._baseLayer.options;
      // original 
      // wmsParams.time = new Date(time).toISOString();
      // hacked
      wmsParams.time = new Date(time).toISOString().slice(0, 19)+'Z';
      return new this._baseLayer.constructor(this._baseLayer.getURL(), wmsParams);
  }
});

The whole code would then look something like this:

<!DOCTYPE html>
<html>

<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.css" />
    <link rel="stylesheet" href="https://cdn.rawgit.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.control.min.css" />
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.2.0/leaflet.js"></script>
    <script type="text/javascript" src="https://cdn.rawgit.com/nezasa/iso8601-js-period/master/iso8601.min.js"></script>
    <script type="text/javascript" src="https://cdn.rawgit.com/socib/Leaflet.TimeDimension/master/dist/leaflet.timedimension.min.js"></script>
</head>

<body>
    <div id="map" style='width: 943px; height: 480px;'></div>
    <script>
      L.TimeDimension.Layer.WMS.include({
        _createLayerForTime: function(time){
            var wmsParams = this._baseLayer.options;
            wmsParams.time = new Date(time).toISOString().slice(0, 19)+'Z';
            return new this._baseLayer.constructor(this._baseLayer.getURL(), wmsParams);
        }
      });

      var wmsLayerRadarRrai4kmLink = 'https://geo.weather.gc.ca/geomet?'

      var wmsLayerRadarRrai4km = L.tileLayer.wms(wmsLayerRadarRrai4kmLink, {
        layers: 'RADAR_RRAI',
        version: '1.3.0',
        format: 'image/png',
        transparent: true
      });

      var wmsLayerRadarRrai4kmTD = L.timeDimension.layer.wms(wmsLayerRadarRrai4km, {
      });

      var map = L.map('map', {
        center: [49.9, -97.215],
        zoom: 5,
        fullScreenControl: true,
        timeDimension: true,
        timeDimensionControl: true,
        timeDimensionOptions: {
        },
        timeDimensionControlOptions: {
          autoPlay: false, 
          playerOptions: {
          loop: false,
          timeSteps: 1,
          }
        }
      });

      var overlayMaps = {
        "Radar Rain 4km": wmsLayerRadarRrai4kmTD
      };

      var basemapDark =  L.tileLayer('https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}  {r}.png', {
          attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors &copy;<a href="https://carto.com/attributions">CARTO</a>',
          subdomains: 'abcd',
        maxZoom: 19
      });

      var basemapLight = L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          maxZoom: 19,
          attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
      });

      var baseMaps = {
        "Light": basemapLight,
        "Dark": basemapDark
      };

      L.control.layers(baseMaps, overlayMaps).addTo(map);
      L.control.timeDimension;
    </script>
</body>

</html>
2
  • Thanks for your reply. I have been going at this for quite some time now and could not figure out the issue. The issue with the TimeDimension plugin could be narrowed down by loading a number of radar images into their own variables and animate that way. Is there a way to get the most recent time associated with the radar image in order to perform a time-specific image search under the L.tileLayer.wms(layer, {time: }); option? I would like to plug the latest time associated with the image and store in a var to use there and subtract 10min from that var to get the next param. – Clip Clippy May 7 '19 at 20:21
  • See my modified answer for solution. – TomazicM May 8 '19 at 19:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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