Leaflet – How to Load GeoJSON Polygon Time Series with Leaflet Time Dimension Plugin

geojsonleaflettime seriestimeslider

I have a GeoJSON file with time series data, representing repeating polygons with varying data. I have managed to display the data for one time interval (a subset of the data representing one interval) using Leaflet but have so far failed to animate the data using the Leaflet Timedimension plugin (I tried with a subset representing 2 intervals). My data is repeating every one hour, the geometry is the same while the attribute value is changing every hour. I keep getting "Time not available" on the plugin control.

My data has an attribute field called time and the date is in this format:

"time": "2006-03-11 09:00:00"

This is one feature from the GeoJSON data:

{ "type": "Feature", "id": -1549271008, "properties": { "id": 827793, "time": "2006-03-11 08:00:00", "insol": 61.73542 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 39.151222675648221, 34.199670805202523 ], [ 39.151222675712766, 34.199675276071595 ], [ 39.151228272367668, 34.199675276015682 ], [ 39.151228272302838, 34.199670805146624 ], [ 39.151222675648221, 34.199670805202523 ] ] ] } }

I have loaded the relevant js libraries for TimeDimension to work (plus the CSS):

<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>

The JavaScript code is at JSFiddle

I'm not sure if the time format is wrong or if I simply have the wrong code for loading the data using the TimeDimension plugin. I have looked through the examples and elsewhere but didn't see something that resembles my case.

So what is the correct way to load a GeoJSON polygon dataset with hourly interval repeating geometry using the Leaflet TimeDimension plugin?

Best Answer

You guessed right, time format is wrong. In Leaflet TimeDimension plugin time is parsed with Java Script function Date.parse(dateTime). This function accepts date/time strings in IETF RFC 2822 format or Ecma-262 5.1 format.

The right format for your time would then be 2006/03/11 09:00:00 or 2006-03-11T09:00:00.

EDIT: From your comment below I understand you are loading GeoJSON layer as GeoJSON object. Parameter layer in L.timeDimension.layer.geoJson(layer) has to be Leaflet layer. You first have to load GeoJSON as Leaflet layer and then use it in L.timeDimension.layer.geoJson call.

This code worked for me:

var timeSeriesGeoJSON =
   {"features": [
       { "type": "Feature", "id": -1549271008, "properties": { "id": 827793, "time": "2006-03-11T08:00:00", "insol": 61.73542 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 39.151222675648221, 34.199670805202523 ], [ 39.151222675712766, 34.199675276071595 ], [ 39.151228272367668, 34.199675276015682 ], [ 39.151228272302838, 34.199670805146624 ], [ 39.151222675648221, 34.199670805202523 ] ] ] } },
       { "type": "Feature", "id": -1549271008, "properties": { "id": 827794, "time": "2006-03-11T09:00:00", "insol": 161.73542 }, "geometry": { "type": "Polygon", "coordinates": [ [ [ 39.151222675648221, 34.199670805202523 ], [ 39.151222675712766, 34.199675276071595 ], [ 39.151228272367668, 34.199675276015682 ], [ 39.151228272302838, 34.199670805146624 ], [ 39.151222675648221, 34.199670805202523 ] ] ] } }
     ],
    "type":"FeatureCollection"
   };

var map = L.map('map').fitBounds([[34.1995508059065,39.151200914031406],[34.199696966261726,39.15145937135462]]);

var timeDimension = new L.TimeDimension({
        period: "PT1H",
    });
map.timeDimension = timeDimension; 

var player = new L.TimeDimension.Player({
    transitionTime: 100, 
    loop: false,
    startOver:true
}, timeDimension);
var timeDimensionControlOptions = {
    player:        player,
    timeDimension: timeDimension,
    position:      'bottomleft',
    autoPlay:      true,
    minSpeed:      1,
    speedStep:     1,
    maxSpeed:      15,
    timeSliderDragUpdate: true
};
var timeDimensionControl = new L.Control.TimeDimension(timeDimensionControlOptions);

map.addControl(timeDimensionControl);

function getColor(d) {
    return d > 420 ? 'rgba(215,25,28,1.0)' :
        d > 360  ? 'rgba(237,110,67,1.0)' :
        d > 300  ? 'rgba(254,186,110,1.0)' :
        d > 240  ? 'rgba(255,232,164,1.0)' :
        d > 180   ? 'rgba(231,245,203,1.0)' :
        d > 120   ? 'rgba(183,223,227,1.0)' :
        d > 60   ? 'rgba(117,177,211,1.0)' :
              'rgba(44,123,182,1.0)';
  }

function style(feature) {
    return {
      weight: 2,
      opacity: 1,
      color: 'rgba(35,35,35,1.0)',
      dashArray: '',
      fillOpacity: 1,
      fillColor: getColor(feature.properties.insol)
    };
  }

var timeSeriesLayer = L.geoJSON(timeSeriesGeoJSON, {style: style});

var geojson = L.timeDimension.layer.geoJson(timeSeriesLayer);

geojson.addTo(map);

var legend = L.control({position: 'bottomright'});

legend.onAdd = function (map) {

  var div = L.DomUtil.create('div', 'info legend'),
    grades = [0, 60, 120, 180, 240, 300, 360, 420],
    labels = ['Values in Wh/m<sup>2</sup>'],
    from, to;

  for (var i = 0; i < grades.length; i++) {
    from = grades[i];
    to = grades[i + 1];

    labels.push(
      '<i style="background:' + getColor(from + 1) + '"></i> ' +
      from + (to ? '&ndash;' + to : '+'));
  }

  div.innerHTML = labels.join('<br>');
  return div;
};

legend.addTo(map);