Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added fade and interpolation for wms layers #149

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,10 @@ Option | Type | Default
`getCapabilitiesLayerName` | `String` | `null` | Alternative layer name for the GetCapabilities request (useful if using a cache service like GeoWebCache)
`setDefaultTime` | `Boolean` | `false` | If true, it will change the current time to the default time of the layer (according to getCapabilities)
`wmsVersion` | `String` | `layer.options.version` or `"1.1.1"` | WMS version of the layer. Used to construct the getCapabilities request
`fadeFrames` | `Number` | `1` | Number of animation frames over which to fade in and fade out layers, using css opacity.
`fadeInFrames` | `Number` | `layer.options.fadeFrames` | Number of animation frames over which to fade in and layers, using css opacity. 10 might be a good option.
`fadeOutFrames` | `Number` | `layer.options.fadeFrames` | Number of animation frames over which to fade out layers, using css opacity. 8 might be a good option.
`interpolate` | `Boolean` | `false` | Whether gradually fade through layers, using css opacity, over the duration. If using this feature, probably also set fadeOutFrames. (The interpolate option takes precedence over fadeInFrames, if both were specified).


### L.TimeDimension.Layer.GeoJSON
Expand Down Expand Up @@ -341,12 +345,12 @@ Update mode can be one of these values: `intersect`, `union`, `replace`, `extrem
## Talks
- Leaflet.TimeDimension: ¡esto se anima!(esp)
[10as Jornadas SIG libre. Girona 2016](http://www.sigte.udg.edu/jornadassiglibre2016/) |
[Video](https://vimeo.com/172724621) |
[Video](https://vimeo.com/172724621) |
[Slides](http://apps.socib.es/Leaflet.TimeDimension/slides/slides-siglibre10.html)

- Leaflet.TimeDimension webinar (eng)
[Interoperability and Technology/Tech Dive Webinar Series](http://wiki.esipfed.org/index.php/Interoperability_and_Technology/Tech_Dive_Webinar_Series) from [ESIP](http://www.esipfed.org/) |
[Video](https://www.youtube.com/watch?v=US5FUUPqlww) |
[Video](https://www.youtube.com/watch?v=US5FUUPqlww) |
[Slides](http://apps.socib.es/Leaflet.TimeDimension/slides/slides-esip.html)


Expand Down
25 changes: 15 additions & 10 deletions src/leaflet.timedimension.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ L.TimeDimension = (L.Layer || L.Class).extend({
return this._currentTimeIndex;
},

getInterpolator: function(){
return this._interp;
},

getCurrentTime: function () {
var index = -1;
if (this._loadingTimeIndex !== -1) {
Expand All @@ -58,7 +62,8 @@ L.TimeDimension = (L.Layer || L.Class).extend({
return (this._loadingTimeIndex !== -1);
},

setCurrentTimeIndex: function (newIndex) {
setCurrentTimeIndex: function (newIndex,interp) {
this._interp = interp || {position: function(){return 1;}};
var upperLimit = this._upperLimit || this._availableTimes.length - 1;
var lowerLimit = this._lowerLimit || 0;
//clamp the value
Expand All @@ -68,7 +73,7 @@ L.TimeDimension = (L.Layer || L.Class).extend({
}
this._loadingTimeIndex = newIndex;
var newTime = this._availableTimes[newIndex];
console.log('INIT -- Current time: ' + new Date(newTime).toISOString());
//console.log('INIT -- Current time: ' + new Date(newTime).toISOString());
if (this._checkSyncedLayersReady(this._availableTimes[this._loadingTimeIndex])) {
this._newTimeIndexLoaded();
} else {
Expand All @@ -78,7 +83,7 @@ L.TimeDimension = (L.Layer || L.Class).extend({
// add timeout of 3 seconds if layers doesn't response
setTimeout((function (index) {
if (index == this._loadingTimeIndex) {
console.log('Change time for timeout');
//console.log('Change time for timeout');
this._newTimeIndexLoaded();
}
}).bind(this, newIndex), this._loadingTimeout);
Expand All @@ -91,25 +96,25 @@ L.TimeDimension = (L.Layer || L.Class).extend({
return;
}
var time = this._availableTimes[this._loadingTimeIndex];
console.log('END -- Current time: ' + new Date(time).toISOString());
//console.log('END -- Current time: ' + new Date(time).toISOString());
this._currentTimeIndex = this._loadingTimeIndex;
this.fire('timeload', {
time: time
});
this._loadingTimeIndex = -1;
},

_checkSyncedLayersReady: function (time) {
for (var i = 0, len = this._syncedLayers.length; i < len; i++) {
if (this._syncedLayers[i].isReady) {
if (!this._syncedLayers[i].isReady(time)) {
return false;
return false;
}
}
}
return true;
},

setCurrentTime: function (time) {
var newIndex = this._seekNearestTimeIndex(time);
this.setCurrentTimeIndex(newIndex);
Expand All @@ -120,7 +125,7 @@ L.TimeDimension = (L.Layer || L.Class).extend({
return this._availableTimes[index];
},

nextTime: function (numSteps, loop) {
nextTime: function (numSteps, loop, interp) {
if (!numSteps) {
numSteps = 1;
}
Expand All @@ -146,7 +151,7 @@ L.TimeDimension = (L.Layer || L.Class).extend({
newIndex = lowerLimit;
}
}
this.setCurrentTimeIndex(newIndex);
this.setCurrentTimeIndex(newIndex,interp);
},

prepareNextTimes: function (numSteps, howmany, loop) {
Expand Down Expand Up @@ -328,7 +333,7 @@ L.TimeDimension = (L.Layer || L.Class).extend({
availableTimes: this._availableTimes,
currentTime: currentTime
});
console.log('available times changed');
//console.log('available times changed');
},
getLowerLimit: function () {
return this._availableTimes[this.getLowerLimitIndex()];
Expand Down
134 changes: 103 additions & 31 deletions src/leaflet.timedimension.layer.wms.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ L.TimeDimension.Layer.WMS = L.TimeDimension.Layer.extend({
this._updateTimeDimension = this.options.updateTimeDimension || false;
this._setDefaultTime = this.options.setDefaultTime || false;
this._updateTimeDimensionMode = this.options.updateTimeDimensionMode || 'intersect'; // 'union' or 'replace'
this._fadeFrames = parseFloat(this.options.fadeFrames) || 1;
this._fadeInFrames = this.options.fadeInFrames? parseFloat(this.options.fadeInFrames) || this._fadeFrames : this._fadeFrames;
this._fadeOutFrames = this.options.fadeInFrames? parseFloat(this.options.fadeInFrames) || this._fadeFrames : this._fadeFrames;
this._interpolate = this.options.interpolate || false;
this._layers = {};
this._defaultTime = 0;
this._availableTimes = [];
Expand Down Expand Up @@ -89,7 +93,7 @@ L.TimeDimension.Layer.WMS = L.TimeDimension.Layer.extend({
if (!this._map.hasLayer(layer)) {
this._map.addLayer(layer);
} else {
this._showLayer(layer, time);
this._showLayer(layer, time, this._timeDimension.getInterpolator());
}
},

Expand Down Expand Up @@ -160,19 +164,23 @@ L.TimeDimension.Layer.WMS = L.TimeDimension.Layer.extend({
}
}
},
_showLayer: function(layer, time) {
if (this._currentLayer && this._currentLayer !== layer) {
this._currentLayer.hide();
_showLayer: function(layer, time, interp) {
if(!(this._interpolate && interp)){
interp = new LtdwGlide(this._fadeInFrames);
}
layer.show(interp).then(function(oldLayer, newLayer){
if (oldLayer && oldLayer !== newLayer) {
oldLayer.hide(new LtdwGlide(this._fadeOutFrames));
}
layer.show();
if (this._currentLayer && this._currentLayer === layer) {
return;
}
this._currentLayer = layer;
this._currentTime = time;
console.log('Show layer ' + layer.wmsParams.layers + ' with time: ' + new Date(time).toISOString());

this._evictCachedTimes(this._timeCacheForward, this._timeCacheBackward);
}.bind(this,this._currentLayer, layer));

if (this._currentLayer && this._currentLayer === layer) {
return;
}
this._currentLayer = layer;
this._currentTime = time;
//console.log('Show layer ' + layer.wmsParams.layers + ' with time: ' + new Date(time).toISOString());
},

_getLayerForTime: function(time) {
Expand All @@ -199,7 +207,7 @@ L.TimeDimension.Layer.WMS = L.TimeDimension.Layer.extend({
this._layers[time] = layer;
}
if (this._timeDimension && time == this._timeDimension.getCurrentTime() && !this._timeDimension.isLoading()) {
this._showLayer(layer, time);
this._showLayer(layer, time, this._timeDimension.getInterpolator());
}
// console.log('Loaded layer ' + layer.wmsParams.layers + ' with time: ' + new Date(time).toISOString());
this.fire('timeload', {
Expand Down Expand Up @@ -235,6 +243,7 @@ L.TimeDimension.Layer.WMS = L.TimeDimension.Layer.extend({
},

_removeLayers: function(times) {
return;
for (var i = 0, l = times.length; i < l; i++) {
if (this._map)
this._map.removeLayer(this._layers[times[i]]);
Expand All @@ -260,11 +269,13 @@ L.TimeDimension.Layer.WMS = L.TimeDimension.Layer.extend({
var oReq = new XMLHttpRequest();
oReq.addEventListener("load", (function(xhr) {
var data = xhr.currentTarget.responseXML;
this._defaultTime = Date.parse(this._getDefaultTimeFromCapabilities(data));
this._setDefaultTime = this._setDefaultTime || (this._timeDimension && this._timeDimension.getAvailableTimes().length == 0);
this.setAvailableTimes(this._parseTimeDimensionFromCapabilities(data));
if (this._setDefaultTime && this._timeDimension) {
if(data){
this._defaultTime = Date.parse(this._getDefaultTimeFromCapabilities(data));
this._setDefaultTime = this._setDefaultTime || (this._timeDimension && this._timeDimension.getAvailableTimes().length == 0);
this.setAvailableTimes(this._parseTimeDimensionFromCapabilities(data));
if (this._setDefaultTime && this._timeDimension) {
this._timeDimension.setCurrentTime(this._defaultTime);
}
}
}).bind(this));
oReq.overrideMimeType('application/xml');
Expand Down Expand Up @@ -402,6 +413,65 @@ if (!L.NonTiledLayer) {
L.NonTiledLayer = (L.Layer || L.Class).extend({});
}

var LtdwGlide = function(n){
this._position = 0.;
this._step = 1/n;
};
LtdwGlide.prototype.position = function(){
this._position += this._step;
return this._position > 1? 1: this._position;
};
/*
* returns a promise to fade out an element using css opacity.
*/
function ltdlwFadeOut(el,interp){
return new Promise(function(resolve,reject){
if(!el){
resolve();
return;
}
interp = interp || new LtdwGlide(7);
var startOpacity = parseFloat(el.style.opacity);
(function fade() {
var opacity = startOpacity * (1-interp.position());
if(opacity >= 0.1){
el.style.opacity = opacity;
requestAnimationFrame(fade);
}else{
el.style.display = 'none';
el.style.opacity = startOpacity;
resolve();
}
})();
});
}
/*
* returns a promise to fade in an element using css opacity.
*/
function ltdlwFadeIn(el, interp){
return new Promise(function(resolve,reject){
if(!el){
resolve();
return;
}
var targetOpacity = parseFloat(el.style.opacity) || 1;
interp = interp || new LtdwGlide(10);
el.style.opacity = 0;
el.style.display = "block";
(function fade() {
var position = interp.position();
if ( position < 1 ) {
el.style.opacity = position * targetOpacity;
requestAnimationFrame(fade);
}else{
el.style.opacity = targetOpacity;
resolve();
}
})();
});

}

L.NonTiledLayer.include({
_visible: true,
_loaded: false,
Expand Down Expand Up @@ -429,14 +499,17 @@ L.NonTiledLayer.include({
return this._loaded;
},

hide: function() {
this._visible = false;
this._div.style.display = 'none';
hide: function(interp) {
return ltdlwFadeOut(this._div,interp).then(
function(){
this._visible = false;
}.bind(this)
);
},

show: function() {
show: function(interp) {
this._visible = true;
this._div.style.display = 'block';
return ltdlwFadeIn(this._div,interp);
},

getURL: function() {
Expand Down Expand Up @@ -466,18 +539,17 @@ L.TileLayer.include({
return this._loaded;
},

hide: function() {
this._visible = false;
if (this._container) {
this._container.style.display = 'none';
}
hide: function(interp) {
return ltdlwFadeOut(this._container,interp).then(
function(){
this._visible = false;
}.bind(this)
);
},

show: function() {
show: function(interp) {
this._visible = true;
if (this._container) {
this._container.style.display = 'block';
}
return ltdlwFadeIn(this._container,interp);
},

getURL: function() {
Expand Down
25 changes: 19 additions & 6 deletions src/leaflet.timedimension.player.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
/*jshint indent: 4, browser:true*/
/*global L*/


/*
* L.TimeDimension.Interpolator
*/
//'use strict';
var LtdInterpolator = function(transitionTime,interp){
this._start_time = new Date().getTime();
this._transitionTime = transitionTime;
this._start_position = interp ? interp.position() : 0.;
};
LtdInterpolator.prototype.position = function(){
var position = (new Date().getTime() - this._start_time) / this._transitionTime;
return position > 1? 1.:position;
}
/*
* L.TimeDimension.Player
*/
Expand All @@ -23,7 +35,7 @@ L.TimeDimension.Player = (L.Layer || L.Class).extend({
this._waitingForBuffer = false; // reset buffer
}).bind(this));
this.setTransitionTime(this.options.transitionTime || 1000);

this._timeDimension.on('limitschanged availabletimeschanged timeload', (function(data) {
this._timeDimension.prepareNextTimes(this._steps, this._minBufferReady, this._loop);
}).bind(this));
Expand Down Expand Up @@ -82,14 +94,15 @@ L.TimeDimension.Player = (L.Layer || L.Class).extend({
}
}
this.pause();
this._timeDimension.nextTime(this._steps, this._loop);
this._interp = new LtdInterpolator(this._transitionTime);
this._timeDimension.nextTime(this._steps, this._loop, this._interp);
if (buffer > 0) {
this._timeDimension.prepareNextTimes(this._steps, buffer, this._loop);
}
},

_getMaxIndex: function(){
return Math.min(this._timeDimension.getAvailableTimes().length - 1,
return Math.min(this._timeDimension.getAvailableTimes().length - 1,
this._timeDimension.getUpperLimitIndex() || Infinity);
},

Expand All @@ -99,7 +112,7 @@ L.TimeDimension.Player = (L.Layer || L.Class).extend({
this._waitingForBuffer = false;
if (this.options.startOver){
if (this._timeDimension.getCurrentTimeIndex() === this._getMaxIndex()){
this._timeDimension.setCurrentTimeIndex(this._timeDimension.getLowerLimitIndex() || 0);
this._timeDimension.setCurrentTimeIndex(this._timeDimension.getLowerLimitIndex() || 0, this._interp);
}
}
this.release();
Expand Down