;(function(undefined) {
|
|
'use strict';
|
|
|
|
if (typeof sigma === 'undefined')
|
|
throw 'sigma is not declared';
|
|
|
|
// Initialize packages:
|
|
sigma.utils.pkg('sigma.misc.animation.running');
|
|
|
|
/**
|
|
* Generates a unique ID for the animation.
|
|
*
|
|
* @return {string} Returns the new ID.
|
|
*/
|
|
var _getID = (function() {
|
|
var id = 0;
|
|
return function() {
|
|
return '' + (++id);
|
|
};
|
|
})();
|
|
|
|
/**
|
|
* This function animates a camera. It has to be called with the camera to
|
|
* animate, the values of the coordinates to reach and eventually some
|
|
* options. It returns a number id, that you can use to kill the animation,
|
|
* with the method sigma.misc.animation.kill(id).
|
|
*
|
|
* The available options are:
|
|
*
|
|
* {?number} duration The duration of the animation.
|
|
* {?function} onNewFrame A callback to execute when the animation
|
|
* enter a new frame.
|
|
* {?function} onComplete A callback to execute when the animation
|
|
* is completed or killed.
|
|
* {?(string|function)} easing The name of a function from the package
|
|
* sigma.utils.easings, or a custom easing
|
|
* function.
|
|
*
|
|
* @param {camera} camera The camera to animate.
|
|
* @param {object} target The coordinates to reach.
|
|
* @param {?object} options Eventually an object to specify some options to
|
|
* the function. The available options are
|
|
* presented in the description of the function.
|
|
* @return {number} The animation id, to make it easy to kill
|
|
* through the method "sigma.misc.animation.kill".
|
|
*/
|
|
sigma.misc.animation.camera = function(camera, val, options) {
|
|
if (
|
|
!(camera instanceof sigma.classes.camera) ||
|
|
typeof val !== 'object' ||
|
|
!val
|
|
)
|
|
throw 'animation.camera: Wrong arguments.';
|
|
|
|
if (
|
|
typeof val.x !== 'number' &&
|
|
typeof val.y !== 'number' &&
|
|
typeof val.ratio !== 'number' &&
|
|
typeof val.angle !== 'number'
|
|
)
|
|
throw 'There must be at least one valid coordinate in the given val.';
|
|
|
|
var fn,
|
|
id,
|
|
anim,
|
|
easing,
|
|
duration,
|
|
initialVal,
|
|
o = options || {},
|
|
start = sigma.utils.dateNow();
|
|
|
|
// Store initial values:
|
|
initialVal = {
|
|
x: camera.x,
|
|
y: camera.y,
|
|
ratio: camera.ratio,
|
|
angle: camera.angle
|
|
};
|
|
|
|
duration = o.duration;
|
|
easing = typeof o.easing !== 'function' ?
|
|
sigma.utils.easings[o.easing || 'quadraticInOut'] :
|
|
o.easing;
|
|
|
|
fn = function() {
|
|
var coef,
|
|
t = o.duration ? (sigma.utils.dateNow() - start) / o.duration : 1;
|
|
|
|
// If the animation is over:
|
|
if (t >= 1) {
|
|
camera.isAnimated = false;
|
|
camera.goTo({
|
|
x: val.x !== undefined ? val.x : initialVal.x,
|
|
y: val.y !== undefined ? val.y : initialVal.y,
|
|
ratio: val.ratio !== undefined ? val.ratio : initialVal.ratio,
|
|
angle: val.angle !== undefined ? val.angle : initialVal.angle
|
|
});
|
|
|
|
cancelAnimationFrame(id);
|
|
delete sigma.misc.animation.running[id];
|
|
|
|
// Check callbacks:
|
|
if (typeof o.onComplete === 'function')
|
|
o.onComplete();
|
|
|
|
// Else, let's keep going:
|
|
} else {
|
|
coef = easing(t);
|
|
camera.isAnimated = true;
|
|
camera.goTo({
|
|
x: val.x !== undefined ?
|
|
initialVal.x + (val.x - initialVal.x) * coef :
|
|
initialVal.x,
|
|
y: val.y !== undefined ?
|
|
initialVal.y + (val.y - initialVal.y) * coef :
|
|
initialVal.y,
|
|
ratio: val.ratio !== undefined ?
|
|
initialVal.ratio + (val.ratio - initialVal.ratio) * coef :
|
|
initialVal.ratio,
|
|
angle: val.angle !== undefined ?
|
|
initialVal.angle + (val.angle - initialVal.angle) * coef :
|
|
initialVal.angle
|
|
});
|
|
|
|
// Check callbacks:
|
|
if (typeof o.onNewFrame === 'function')
|
|
o.onNewFrame();
|
|
|
|
anim.frameId = requestAnimationFrame(fn);
|
|
}
|
|
};
|
|
|
|
id = _getID();
|
|
anim = {
|
|
frameId: requestAnimationFrame(fn),
|
|
target: camera,
|
|
type: 'camera',
|
|
options: o,
|
|
fn: fn
|
|
};
|
|
sigma.misc.animation.running[id] = anim;
|
|
|
|
return id;
|
|
};
|
|
|
|
/**
|
|
* Kills a running animation. It triggers the eventual onComplete callback.
|
|
*
|
|
* @param {number} id The id of the animation to kill.
|
|
* @return {object} Returns the sigma.misc.animation package.
|
|
*/
|
|
sigma.misc.animation.kill = function(id) {
|
|
if (arguments.length !== 1 || typeof id !== 'number')
|
|
throw 'animation.kill: Wrong arguments.';
|
|
|
|
var o = sigma.misc.animation.running[id];
|
|
|
|
if (o) {
|
|
cancelAnimationFrame(id);
|
|
delete sigma.misc.animation.running[o.frameId];
|
|
|
|
if (o.type === 'camera')
|
|
o.target.isAnimated = false;
|
|
|
|
// Check callbacks:
|
|
if (typeof (o.options || {}).onComplete === 'function')
|
|
o.options.onComplete();
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Kills every running animations, or only the one with the specified type,
|
|
* if a string parameter is given.
|
|
*
|
|
* @param {?(string|object)} filter A string to filter the animations to kill
|
|
* on their type (example: "camera"), or an
|
|
* object to filter on their target.
|
|
* @return {number} Returns the number of animations killed
|
|
* that way.
|
|
*/
|
|
sigma.misc.animation.killAll = function(filter) {
|
|
var o,
|
|
id,
|
|
count = 0,
|
|
type = typeof filter === 'string' ? filter : null,
|
|
target = typeof filter === 'object' ? filter : null,
|
|
running = sigma.misc.animation.running;
|
|
|
|
for (id in running)
|
|
if (
|
|
(!type || running[id].type === type) &&
|
|
(!target || running[id].target === target)
|
|
) {
|
|
o = sigma.misc.animation.running[id];
|
|
cancelAnimationFrame(o.frameId);
|
|
delete sigma.misc.animation.running[id];
|
|
|
|
if (o.type === 'camera')
|
|
o.target.isAnimated = false;
|
|
|
|
// Increment counter:
|
|
count++;
|
|
|
|
// Check callbacks:
|
|
if (typeof (o.options || {}).onComplete === 'function')
|
|
o.options.onComplete();
|
|
}
|
|
|
|
return count;
|
|
};
|
|
|
|
/**
|
|
* Returns "true" if any animation that is currently still running matches
|
|
* the filter given to the function.
|
|
*
|
|
* @param {string|object} filter A string to filter the animations to kill
|
|
* on their type (example: "camera"), or an
|
|
* object to filter on their target.
|
|
* @return {boolean} Returns true if any running animation
|
|
* matches.
|
|
*/
|
|
sigma.misc.animation.has = function(filter) {
|
|
var id,
|
|
type = typeof filter === 'string' ? filter : null,
|
|
target = typeof filter === 'object' ? filter : null,
|
|
running = sigma.misc.animation.running;
|
|
|
|
for (id in running)
|
|
if (
|
|
(!type || running[id].type === type) &&
|
|
(!target || running[id].target === target)
|
|
)
|
|
return true;
|
|
|
|
return false;
|
|
};
|
|
}).call(this);
|