diff --git a/HISTORY.md b/HISTORY.md
index 2f9d01d9..75d98f06 100644
--- a/HISTORY.md
+++ b/HISTORY.md
@@ -24,6 +24,8 @@ http://visjs.org
`4-8h` to `h4-h8`.
- Deprecated option `showCustomTime`. Use method `addCustomTime()` instead.
- Deprecated event `finishedRedraw` as it's redundant.
+- Renamed option `animate` to `animation`, and changed it to be either a boolean
+ or an object `{duration: number, easingFunction: string}`.
### Network
diff --git a/docs/timeline.html b/docs/timeline.html
index 832044ca..2c9f8aaa 100644
--- a/docs/timeline.html
+++ b/docs/timeline.html
@@ -880,7 +880,8 @@ var options = {
Adjust the visible window such that it fits all items. See also function focus(id).
Available options:
-
animate: boolean | number If true (default), the range is animated smoothly to the new window. If a number, the number is taken as duration for the animation. Default duration is 500 ms.
+
animation: boolean | {duration: number, easingFunction: string} If true (default) or an Object, the range is animated smoothly to the new window. An object can be provided to specify duration and easing function. Default duration is 500 ms, and default easing function is 'easeInOutQuad'. Available easing functions: "linear", "easeInQuad", "easeOutQuad", "easeInOutQuad", "easeInCubic", "easeOutCubic", "easeInOutCubic", "easeInQuart", "easeOutQuart", "easeInOutQuart", "easeInQuint", "easeOutQuint", "easeInOutQuint".
+
@@ -890,7 +891,7 @@ var options = {
none
Adjust the visible window such that the selected item (or multiple items) are centered on screen. See also function fit(). Available options:
-
animate: boolean | number If true (default), the range is animated smoothly to the new window. If a number, the number is taken as duration for the animation. Default duration is 500 ms.
+
animation: boolean | {duration: number, easingFunction: string} If true (default) or an Object, the range is animated smoothly to the new window. An object can be provided to specify duration and easing function. Default duration is 500 ms, and default easing function is 'easeInOutQuad'. Available easing functions: "linear", "easeInQuad", "easeOutQuad", "easeInOutQuad", "easeInCubic", "easeOutCubic", "easeInOutCubic", "easeInQuart", "easeOutQuart", "easeInOutQuart", "easeInQuint", "easeOutQuint", "easeInOutQuint".
@@ -952,7 +953,7 @@ var options = {
none
Move the window such that given time is centered on screen. Parameter time can be a Date, Number, or String. Available options:
-
animate: boolean | number If true (default), the range is animated smoothly to the new window. If a number, the number is taken as duration for the animation. Default duration is 500 ms.
+
animation: boolean | {duration: number, easingFunction: string} If true (default) or an Object, the range is animated smoothly to the new window. An object can be provided to specify duration and easing function. Default duration is 500 ms, and default easing function is 'easeInOutQuad'. Available easing functions: "linear", "easeInQuad", "easeOutQuad", "easeInOutQuad", "easeInCubic", "easeOutCubic", "easeInOutCubic", "easeInQuart", "easeOutQuart", "easeInOutQuart", "easeInQuint", "easeOutQuint", "easeInOutQuint".
@@ -1047,7 +1048,7 @@ var options = {
Select one or multiple items by their id. The currently selected items will be unselected. To unselect all selected items, call `setSelection([])`. Available options:
focus: boolean If true, focus will be set to the selected item(s)
-
animate: boolean | number If true (default), the range is animated smoothly to the new window. If a number, the number is taken as duration for the animation. Default duration is 500 ms. Only applicable when option focus is true.
+
animation: boolean | {duration: number, easingFunction: string} If true (default) or an Object, the range is animated smoothly to the new window. An object can be provided to specify duration and easing function. Default duration is 500 ms, and default easing function is 'easeInOutQuad'. Only applicable when option focus is true. Available easing functions: "linear", "easeInQuad", "easeOutQuad", "easeInOutQuad", "easeInCubic", "easeOutCubic", "easeInOutCubic", "easeInQuart", "easeOutQuart", "easeInOutQuart", "easeInQuint", "easeOutQuint", "easeInOutQuint".
@@ -1057,7 +1058,7 @@ var options = {
none
Set the current visible window. The parameters start and end can be a Date, Number, or String. If the parameter value of start or end is null, the parameter will be left unchanged. Available options:
-
animate: boolean | number If true (default), the range is animated smoothly to the new window. If a number, the number is taken as duration for the animation. Default duration is 500 ms.
+
animation: boolean | {duration: number, easingFunction: string} If true (default) or an Object, the range is animated smoothly to the new window. An object can be provided to specify duration and easing function. Default duration is 500 ms, and default easing function is 'easeInOutQuad'. Available easing functions: "linear", "easeInQuad", "easeOutQuad", "easeInOutQuad", "easeInCubic", "easeOutCubic", "easeInOutCubic", "easeInQuart", "easeOutQuart", "easeInOutQuart", "easeInQuint", "easeOutQuint", "easeInOutQuint".
@@ -1065,6 +1066,7 @@ var options = {
+
Events
Timeline fires events when changing the visible window by dragging, when
diff --git a/examples/timeline/13_past_and_future.html b/examples/timeline/13_past_and_future.html
index 87cff2e0..f11c91fd 100644
--- a/examples/timeline/13_past_and_future.html
+++ b/examples/timeline/13_past_and_future.html
@@ -81,7 +81,7 @@
// set a custom range from -2 minute to +3 minutes current time
var start = new Date((new Date()).getTime() - 2 * 60 * 1000);
var end = new Date((new Date()).getTime() + 3 * 60 * 1000);
- timeline.setWindow(start, end, {animate: false});
+ timeline.setWindow(start, end, {animation: false});
diff --git a/examples/timeline/22_window_adjustment.html b/examples/timeline/22_window_adjustment.html
index 3b4c1f71..cda8325d 100644
--- a/examples/timeline/22_window_adjustment.html
+++ b/examples/timeline/22_window_adjustment.html
@@ -8,6 +8,9 @@
font-family: arial, sans-serif;
font-size: 11pt;
}
+ input {
+ margin: 2px 0;
+ }
@@ -17,14 +20,16 @@
This example demonstrates functions to adjust the visible window of the Timeline.
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -61,9 +66,7 @@
timeline.setWindow('2014-01-01', '2014-04-01');
};
document.getElementById('window2').onclick = function() {
- timeline.setWindow('2014-01-01', '2014-04-01', {
- animate: false
- });
+ timeline.setWindow('2014-01-01', '2014-04-01', {animation: false});
};
document.getElementById('fit').onclick = function() {
timeline.fit();
@@ -77,9 +80,7 @@
timeline.focus(2);
};
document.getElementById('focus2').onclick = function() {
- timeline.focus([5, 6], {
- animate: 3000 // ms
- });
+ timeline.focus([5, 6], {animation: {duration: 3000, easingFunction: 'linear'}}); // ms
};
document.getElementById('focus3').onclick = function() {
var selection = timeline.getSelection();
diff --git a/lib/timeline/Core.js b/lib/timeline/Core.js
index 30c0dd15..e255251f 100644
--- a/lib/timeline/Core.js
+++ b/lib/timeline/Core.js
@@ -432,11 +432,12 @@ Core.prototype.getVisibleItems = function() {
/**
* Set Core window such that it fits all items
* @param {Object} [options] Available options:
- * `animate: boolean | number`
- * If true (default), the range is animated
- * smoothly to the new window.
- * If a number, the number is taken as duration
- * for the animation. Default duration is 500 ms.
+ * `animation: boolean | {duration: number, easingFunction: string}`
+ * If true (default), the range is animated
+ * smoothly to the new window. An object can be
+ * provided to specify duration and easing function.
+ * Default duration is 500 ms, and default easing
+ * function is 'easeInOutQuad'.
*/
Core.prototype.fit = function(options) {
var range = this._getDataRange();
@@ -446,8 +447,8 @@ Core.prototype.fit = function(options) {
return;
}
- var animate = (options && options.animate !== undefined) ? options.animate : true;
- this.range.setRange(range.start, range.end, animate);
+ var animation = (options && options.animation !== undefined) ? options.animation : true;
+ this.range.setRange(range.start, range.end, animation);
};
/**
@@ -492,22 +493,23 @@ Core.prototype._getDataRange = function() {
* @param {Date | Number | String | Object} [start] Start date of visible window
* @param {Date | Number | String} [end] End date of visible window
* @param {Object} [options] Available options:
- * `animate: boolean | number`
- * If true (default), the range is animated
- * smoothly to the new window.
- * If a number, the number is taken as duration
- * for the animation. Default duration is 500 ms.
+ * `animation: boolean | {duration: number, easingFunction: string}`
+ * If true (default), the range is animated
+ * smoothly to the new window. An object can be
+ * provided to specify duration and easing function.
+ * Default duration is 500 ms, and default easing
+ * function is 'easeInOutQuad'.
*/
Core.prototype.setWindow = function(start, end, options) {
- var animate;
+ var animation;
if (arguments.length == 1) {
var range = arguments[0];
- animate = (range.animate !== undefined) ? range.animate : true;
- this.range.setRange(range.start, range.end, animate);
+ animation = (range.animation !== undefined) ? range.animation : true;
+ this.range.setRange(range.start, range.end, animation);
}
else {
- animate = (options && options.animate !== undefined) ? options.animate : true;
- this.range.setRange(start, end, animate);
+ animation = (options && options.animation !== undefined) ? options.animation : true;
+ this.range.setRange(start, end, animation);
}
};
@@ -515,11 +517,12 @@ Core.prototype.setWindow = function(start, end, options) {
* Move the window such that given time is centered on screen.
* @param {Date | Number | String} time
* @param {Object} [options] Available options:
- * `animate: boolean | number`
- * If true (default), the range is animated
- * smoothly to the new window.
- * If a number, the number is taken as duration
- * for the animation. Default duration is 500 ms.
+ * `animation: boolean | {duration: number, easingFunction: string}`
+ * If true (default), the range is animated
+ * smoothly to the new window. An object can be
+ * provided to specify duration and easing function.
+ * Default duration is 500 ms, and default easing
+ * function is 'easeInOutQuad'.
*/
Core.prototype.moveTo = function(time, options) {
var interval = this.range.end - this.range.start;
@@ -527,9 +530,9 @@ Core.prototype.moveTo = function(time, options) {
var start = t - interval / 2;
var end = t + interval / 2;
- var animate = (options && options.animate !== undefined) ? options.animate : true;
+ var animation = (options && options.animation !== undefined) ? options.animation : true;
- this.range.setRange(start, end, animate);
+ this.range.setRange(start, end, animation);
};
/**
diff --git a/lib/timeline/Graph2d.js b/lib/timeline/Graph2d.js
index bb56fe29..75b3c3f5 100644
--- a/lib/timeline/Graph2d.js
+++ b/lib/timeline/Graph2d.js
@@ -151,10 +151,10 @@ Graph2d.prototype.setItems = function(items) {
var start = this.options.start != undefined ? this.options.start : null;
var end = this.options.end != undefined ? this.options.end : null;
- this.setWindow(start, end, {animate: false});
+ this.setWindow(start, end, {animation: false});
}
else {
- this.fit({animate: false});
+ this.fit({animation: false});
}
}
};
diff --git a/lib/timeline/Range.js b/lib/timeline/Range.js
index 6ce5bc0d..69e2ac87 100644
--- a/lib/timeline/Range.js
+++ b/lib/timeline/Range.js
@@ -40,7 +40,7 @@ function Range(body, options) {
this.props = {
touch: {}
};
- this.animateTimer = null;
+ this.animationTimer = null;
// drag listeners for dragging
this.body.emitter.on('panstart', this._onDragStart.bind(this));
@@ -103,27 +103,35 @@ function validateDirection (direction) {
* Set a new start and end range
* @param {Date | Number | String} [start]
* @param {Date | Number | String} [end]
- * @param {boolean | number} [animate=false] If true, the range is animated
- * smoothly to the new window.
- * If animate is a number, the
- * number is taken as duration
- * Default duration is 500 ms.
+ * @param {boolean | {duration: number, easingFunction: string}} [animation=false]
+ * If true (default), the range is animated
+ * smoothly to the new window. An object can be
+ * provided to specify duration and easing function.
+ * Default duration is 500 ms, and default easing
+ * function is 'easeInOutQuad'.
* @param {Boolean} [byUser=false]
*
*/
-Range.prototype.setRange = function(start, end, animate, byUser) {
+Range.prototype.setRange = function(start, end, animation, byUser) {
if (byUser !== true) {
byUser = false;
}
- var _start = start != undefined ? util.convert(start, 'Date').valueOf() : null;
- var _end = end != undefined ? util.convert(end, 'Date').valueOf() : null;
+ var finalStart = start != undefined ? util.convert(start, 'Date').valueOf() : null;
+ var finalEnd = end != undefined ? util.convert(end, 'Date').valueOf() : null;
this._cancelAnimation();
- if (animate) {
+ if (animation) { // true or an Object
var me = this;
var initStart = this.start;
var initEnd = this.end;
- var duration = typeof animate === 'number' ? animate : 500;
+ var duration = (typeof animation === 'object' && 'duration' in animation) ? animation.duration : 500;
+ var easingName = (typeof animation === 'object' && 'easingFunction' in animation) ? animation.easingFunction : 'easeInOutQuad';
+ var easingFunction = util.easingFunctions[easingName];
+ if (!easingFunction) {
+ throw new Error('Unknown easing function ' + JSON.stringify(easingName) + '. ' +
+ 'Choose from: ' + Object.keys(util.easingFunctions).join(', '));
+ }
+
var initTime = new Date().valueOf();
var anyChanged = false;
@@ -131,9 +139,10 @@ Range.prototype.setRange = function(start, end, animate, byUser) {
if (!me.props.touch.dragging) {
var now = new Date().valueOf();
var time = now - initTime;
+ var ease = easingFunction(time / duration);
var done = time > duration;
- var s = (done || _start === null) ? _start : util.easeInOutQuad(time, initStart, _start, duration);
- var e = (done || _end === null) ? _end : util.easeInOutQuad(time, initEnd, _end, duration);
+ var s = (done || finalStart === null) ? finalStart : initStart + (finalStart - initStart) * ease;
+ var e = (done || finalEnd === null) ? finalEnd : initEnd + (finalEnd - initEnd) * ease;
changed = me._applyRange(s, e);
DateUtil.updateHiddenDates(me.body, me.options.hiddenDates);
@@ -150,7 +159,7 @@ Range.prototype.setRange = function(start, end, animate, byUser) {
else {
// animate with as high as possible frame rate, leave 20 ms in between
// each to prevent the browser from blocking
- me.animateTimer = setTimeout(next, 20);
+ me.animationTimer = setTimeout(next, 20);
}
}
};
@@ -158,7 +167,7 @@ Range.prototype.setRange = function(start, end, animate, byUser) {
return next();
}
else {
- var changed = this._applyRange(_start, _end);
+ var changed = this._applyRange(finalStart, finalEnd);
DateUtil.updateHiddenDates(this.body, this.options.hiddenDates);
if (changed) {
var params = {start: new Date(this.start), end: new Date(this.end), byUser:byUser};
@@ -173,9 +182,9 @@ Range.prototype.setRange = function(start, end, animate, byUser) {
* @private
*/
Range.prototype._cancelAnimation = function () {
- if (this.animateTimer) {
- clearTimeout(this.animateTimer);
- this.animateTimer = null;
+ if (this.animationTimer) {
+ clearTimeout(this.animationTimer);
+ this.animationTimer = null;
}
};
diff --git a/lib/timeline/Timeline.js b/lib/timeline/Timeline.js
index 7cc6445a..99714624 100644
--- a/lib/timeline/Timeline.js
+++ b/lib/timeline/Timeline.js
@@ -177,10 +177,10 @@ Timeline.prototype.setItems = function(items) {
var start = this.options.start != undefined ? this.options.start : dataRange.start;
var end = this.options.end != undefined ? this.options.end : dataRange.end;
- this.setWindow(start, end, {animate: false});
+ this.setWindow(start, end, {animation: false});
}
else {
- this.fit({animate: false});
+ this.fit({animation: false});
}
}
};
@@ -230,11 +230,12 @@ Timeline.prototype.setData = function (data) {
* @param {Object} [options] Available options:
* `focus: boolean`
* If true, focus will be set to the selected item(s)
- * `animate: boolean | number`
+ * `animation: boolean | {duration: number, easingFunction: string}`
* If true (default), the range is animated
- * smoothly to the new window.
- * If a number, the number is taken as duration
- * for the animation. Default duration is 500 ms.
+ * smoothly to the new window. An object can be
+ * provided to specify duration and easing function.
+ * Default duration is 500 ms, and default easing
+ * function is 'easeInOutQuad'.
* Only applicable when option focus is true.
*/
Timeline.prototype.setSelection = function(ids, options) {
@@ -258,12 +259,12 @@ Timeline.prototype.getSelection = function() {
* are centered on screen.
* @param {String | String[]} id An item id or array with item ids
* @param {Object} [options] Available options:
- * `animate: boolean | number`
+ * `animation: boolean | {duration: number, easingFunction: string}`
* If true (default), the range is animated
- * smoothly to the new window.
- * If a number, the number is taken as duration
- * for the animation. Default duration is 500 ms.
- * Only applicable when option focus is true
+ * smoothly to the new window. An object can be
+ * provided to specify duration and easing function.
+ * Default duration is 500 ms, and default easing
+ * function is 'easeInOutQuad'.
*/
Timeline.prototype.focus = function(id, options) {
if (!this.itemsData || id == undefined) return;
@@ -299,8 +300,8 @@ Timeline.prototype.focus = function(id, options) {
var middle = (start + end) / 2;
var interval = Math.max((this.range.end - this.range.start), (end - start) * 1.1);
- var animate = (options && options.animate !== undefined) ? options.animate : true;
- this.range.setRange(middle - interval / 2, middle + interval / 2, animate);
+ var animation = (options && options.animation !== undefined) ? options.animation : true;
+ this.range.setRange(middle - interval / 2, middle + interval / 2, animation);
}
};
diff --git a/lib/util.js b/lib/util.js
index 60d997d9..6b8ca6d4 100644
--- a/lib/util.js
+++ b/lib/util.js
@@ -1319,25 +1319,6 @@ exports.binarySearchValue = function(orderedItems, target, field, sidePreference
return -1;
};
-/**
- * Quadratic ease-in-out
- * http://gizma.com/easing/
- * @param {number} t Current time
- * @param {number} start Start value
- * @param {number} end End value
- * @param {number} duration Duration
- * @returns {number} Value corresponding with current time
- */
-exports.easeInOutQuad = function (t, start, end, duration) {
- var change = end - start;
- t /= duration/2;
- if (t < 1) return change/2*t*t + start;
- t--;
- return -change/2 * (t*(t-2) - 1) + start;
-};
-
-
-
/*
* Easing Functions - inspired from http://gizma.com/easing/
* only considering the t value for the range [0, 1] => [0, 1]