socib / Leaflet.TimeDimension

Add time dimension capabilities on a Leaflet map.
MIT License
435 stars 138 forks source link

Time seems to be ~5-10 minutes ahead of what the time really is? #77

Open futuretechmag opened 8 years ago

futuretechmag commented 8 years ago

I noticed on your example for the nowCOAST radar (what we're using it for) is the exact same way? I just pulled it up right now (10:30am ET) and it's showing the "current" is 10:33am. Last night it was 1:07am and it was saying the current time was something like 1:17am.

Any ideas what could cause that?

bielfrontera commented 8 years ago

Hi! Check out the response of GetCapabilities in nowCOAST's WMS. They are sending a time extent with the end time on the near future.

Now its 15:03 UTC, and it returns:

<Extent name="time" default="2016-08-11T10:03:00.000Z">
  2016-08-11T10:03:00.000Z/2016-08-11T15:09:00.000Z/PT4M
</Extent>

I've check these specific times in the future, and they show the same images as the last real available time.

futuretechmag commented 8 years ago

Thanks for the comment back, is there any way to specify multiple WMS layers to all share the same play animation, exactly like nowCOAST? To be specific, just like nowCOAST, I don't want to have all of them active and loop, but if nexrad_radar and goes_visible_sat are both active layers, animate them? If all 4 layers are active, animate and loop, etc?

I have this (working) currently, but it's strictly animating the radar.

`var nexrad_radar = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/WMSServer", { layers: '1', format: 'image/png', transparent: true, opacity: 0.5, attribution: 'NOAA nowCOAST NEXRAD',

}), goes_infrared = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/sat_meteo_imagery_goes_time/MapServer/WMSServer", { layers: '1', format: 'image/png', transparent: true, opacity: 0.6, attribution: 'NOAA nowCOAST' }), goes_water_vapor = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/sat_meteo_imagery_goes_time/MapServer/WMSServer", { layers: '5', format: 'image/png', transparent: true, opacity: 0.6, attribution: 'NOAA nowCOAST' }); goes_visible_sat = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/sat_meteo_imagery_goes_time/MapServer/WMSServer", { layers: '9', format: 'image/png', transparent: true, opacity: 0.8, attribution: 'NOAA nowCOAST' });

var proxy = 'leaflet/proxy.php'; var testTimeLayer = L.timeDimension.layer.wms(nexrad_radar, { proxy: proxy, updateTimeDimension: true }); testTimeLayer.addTo(map);

var theLegend = L.control({ position: 'topright' });

var baseMaps = { "Default": CartoDB_Positron };

var overlayMaps = { "NEXRAD Radar": testTimeLayer, "GOES Visible": goes_visible_sat, "GOES Water Vapor": goes_water_vapor, "GOES Infrared": goes_infrared, "Current Observations": current_obs_layer };

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

bielfrontera commented 8 years ago

Yes, you can manage as many layers as you want with the same control. But you must create a timedimension.layer for each one. In your code, you've just created one, for nexrad_radar, and then you have added other regular WMS layers as overlays.

So, define nexradRadarTimeLayer, goesVisibleSatTimeLayer, goesWaterVaporTimeLayer, ... They will probably share the same time extension, so it is not necessary to add the option "updateTimeDimension: true" in each layer.

futuretechmag commented 8 years ago

I don't want to ask an even sillier question, but would I then have to do some if checks, if I do anything like:

var proxy = 'leaflet/proxy.php'; var testTimeLayer = L.timeDimension.layer.wms(nexrad_radar, { proxy: proxy, updateTimeDimension: true }); testTimeLayer.addTo(map);

var proxy1 = 'leaflet/proxy.php'; var testTimeLayer1 = L.timeDimension.layer.wms(goes_visible_sat, { proxy: proxy1,

}); testTimeLayer1.addTo(map);

It adds both to the map as default, and says throws two leaflet.timedimension.js:94 Uncaught RangeError: Invalid time value

futuretechmag commented 8 years ago

I don't think if this would be correct, but it seems to "work":

var proxy = 'leaflet/proxy.php'; var nexradRadarTimeLayer = L.timeDimension.layer.wms(nexrad_radar, { proxy: proxy, updateTimeDimension: true }); nexradRadarTimeLayer.addTo(map);

var goesVisTimeLayer = L.timeDimension.layer.wms(goes_visible_sat, {

}); nexradRadarTimeLayer.addTo(map);

There's a TON of buffering on almost every loop, but it works.

bielfrontera commented 8 years ago

There's a lot of logging because the examples are using the src files. You should use leaflet.timedimension.min.js and leaflet.timedimension.control.min.css that are inside dist folder.

You are adding nexradRadarTimeLayer twice on the map (last line in your code). In the previous comment, your code adds both layers to the map (you are calling addTo). If you only want one layer as default, do not add to the map. Create the timedimension layer and add it to the overlays, but do not call addTo.

futuretechmag commented 8 years ago

Thanks again for the response!

I think I see my issue. I'm not trying to be overly obtuse here, but hear me out. This is the way it currently works.

~~1.) Default page load, the current timestamp radar is pulled. 2.) If, with the radar still active, I was to click any of those other 3 layers, nothing happens (it looks as though the proxy.php is hit and I receive the WMSServer response, but nothing actually happens on the map UNTIL I click play, then the radar and any active layers show and animate.~~

Combining 1 and 2, on a default page load if I was to uncheck the radar and check a different layer, nothing shows until I click play.

What I'm looking to do is always pull in any and all layers that are checked, at the current timestamp. So if the page was freshly loaded, there is a timestamp because the radar is on by default, I'd like for any of these other 3 layers to pull in, again it seems like they do actually.

I had this large thing typed up and then I think I realized something. I don't know how much you know about meteorology or anything, but radar updates every ~5 minutes or so, depending on the source. Satellite images update roughly every ~30 minutes, depending on the source. I was pulling my hair out because I swear it was "working" (as in my problem with the strike-out above) the other day, and I believe what's happening is that, if the default timestamp for the radar is NOT an available time on the satellite nothing pulls. That would make sense because I'm not updating the time on those other layers. The reason I'm not doing THAT is because again, the other layers update every ~30 minutes , while the radar is every ~5 minutes, so if I did update the time every time a layer was added it would cause the radar to now pull in ~30-minute intervals.

So, knowing all that, is there anything that could really help me here in terms of always pulling the latest available image, for the satellite layers when they are first selected

Actually, I don't believe that would work either since if I'm in the middle of playing a loop of the radar and I toggle one of the satellite images, the images would be all out of sync.

I don't really know if you'll have any ideas to throw at me, but I had this all typed out already. Sorry.

In case you do have any ideas, here's my current code:

var map = L.map('map_div', {
    zoom: 5,
    minZoom: 5,
    fullscreenControl: true,
    timeDimension: true,
    timeDimensionControl: true,
    timeDimensionControlOptions: {
        autoPlay: false,
        playerOptions: {
            buffer: 10,
            transitionTime: 250,
            loop: true,
        }
    }
});

var CartoDB_Positron = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> &copy; <a href="http://cartodb.com/attributions">CartoDB</a>',
    subdomains: 'abcd',
    maxZoom: 19
}).addTo(map);

var nexrad_radar = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/WMSServer", {
    layers: '1',
    format: 'image/png',
    transparent: true,
    opacity: 0.5,
    attribution: 'NOAA nowCOAST NEXRAD',

});
var goes_infrared = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/sat_meteo_imagery_goes_time/MapServer/WMSServer", {
    layers: '1',
    format: 'image/png',
    transparent: true,
    opacity: 0.6,
    attribution: 'NOAA nowCOAST'
});
var goes_water_vapor = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/sat_meteo_imagery_goes_time/MapServer/WMSServer", {
    layers: '5',
    format: 'image/png',
    transparent: true,
    opacity: 0.6,
    attribution: 'NOAA nowCOAST'
});
var goes_visible_sat = L.nonTiledLayer.wms("http://new.nowcoast.noaa.gov/arcgis/services/nowcoast/sat_meteo_imagery_goes_time/MapServer/WMSServer", {
    layers: '9',
    format: 'image/png',
    transparent: true,
    opacity: 0.8,
    attribution: 'NOAA nowCOAST'
});

var proxy = './vendor/leaflet/proxy.php';
var nexradRadarTimeLayer = L.timeDimension.layer.wms(nexrad_radar, {
    proxy: proxy,
    updateTimeDimension: true
});

var goesVisTimeLayer = L.timeDimension.layer.wms(goes_visible_sat, {
        proxy: proxy

});

var goesWaterVaporTimeLayer = L.timeDimension.layer.wms(goes_water_vapor, {

          proxy: proxy
});

var goesInfraredTimeLayer = L.timeDimension.layer.wms(goes_infrared, {
        proxy: proxy

});
nexradRadarTimeLayer.addTo(map);

var baseMaps = {
    "Default": CartoDB_Positron
};

var overlayMaps = {
    "NEXRAD Radar": nexradRadarTimeLayer,
    "GOES Visible": goesVisTimeLayer,
    "GOES Water Vapor": goesWaterVaporTimeLayer,
    "GOES Infrared": goesInfraredTimeLayer,
    "Current Observations": current_obs_layer
};

L.control.layers(baseMaps, overlayMaps).addTo(map);
bielfrontera commented 8 years ago

Hi, if you want to add to the map several layers at the same time, and you know that some of them are updated every 30 minutes (and this interesects with other layers that are updated ever 5 minutes), you might load your map with a predefined set of available times:

var currentTime = new Date();
currentTime.setUTCMinutes(0, 0, 0);
var map = L.map('map', {
    ...
    timeDimensionOptions: {
        timeInterval: "P1W/" + currentTime.toISOString(),
        period: "PT30M",
        currentTime: currentTime.getTime()
    },
    ...
});

And you should remove the updateTimeDimension option at the first timeLayer.