@qooxdoo/framework
Version:
The JS Framework for Coders
154 lines (139 loc) • 5.7 kB
JavaScript
/* ************************************************************************
qooxdoo - the new era of web development
http://qooxdoo.org
Copyright:
2012 1&1 Internet AG, Germany, http://www.1und1.de
License:
MIT: https://opensource.org/licenses/MIT
See the LICENSE file in the project's top-level directory for details.
Authors:
* Martin Wittemann (martinwittemann)
************************************************************************ */
/**
* Wrapper for {@link qx.bom.element.AnimationCss} and
* {@link qx.bom.element.AnimationJs}. It offers the public API and decides using
* feature checks either to use CSS animations or JS animations.
*
* If you use this class, the restrictions of the JavaScript animations apply.
* This means that you can not use transforms and custom bezier timing functions.
*/
qx.Bootstrap.define("qx.bom.element.Animation",
{
statics : {
/**
* This function takes care of the feature check and starts the animation.
* It takes a DOM element to apply the animation to, and a description.
* The description should be a map, which could look like this:
*
* <pre class="javascript">
* {
* "duration": 1000,
* "keep": 100,
* "keyFrames": {
* 0 : {"opacity": 1, "scale": 1},
* 100 : {"opacity": 0, "scale": 0}
* },
* "origin": "50% 50%",
* "repeat": 1,
* "timing": "ease-out",
* "alternate": false,
* "delay" : 2000
* }
* </pre>
*
* *duration* is the time in milliseconds one animation cycle should take.
*
* *keep* is the key frame to apply at the end of the animation. (optional)
* Keep in mind that the keep key is reversed in case you use an reverse
* animation or set the alternate key and a even repeat count.
*
* *keyFrames* is a map of separate frames. Each frame is defined by a
* number which is the percentage value of time in the animation. The value
* is a map itself which holds css properties or transforms
* {@link qx.bom.element.Transform} (Transforms only for CSS Animations).
*
* *origin* maps to the transform origin {@link qx.bom.element.Transform#setOrigin}
* (Only for CSS animations).
*
* *repeat* is the amount of time the animation should be run in
* sequence. You can also use "infinite".
*
* *timing* takes one of the predefined value:
* <code>ease</code> | <code>linear</code> | <code>ease-in</code>
* | <code>ease-out</code> | <code>ease-in-out</code> |
* <code>cubic-bezier(<number>, <number>, <number>, <number>)</code>
* (cubic-bezier only available for CSS animations)
*
* *alternate* defines if every other animation should be run in reverse order.
*
* *delay* is the time in milliseconds the animation should wait before start.
*
* @param el {Element} The element to animate.
* @param desc {Map} The animations description.
* @param duration {Integer?} The duration in milliseconds of the animation
* which will override the duration given in the description.
* @return {qx.bom.element.AnimationHandle} AnimationHandle instance to control
* the animation.
*/
animate : function(el, desc, duration) {
var onlyCssKeys = qx.bom.element.Animation.__hasOnlyCssKeys(el, desc.keyFrames);
if (qx.core.Environment.get("css.animation") && onlyCssKeys) {
return qx.bom.element.AnimationCss.animate(el, desc, duration);
} else {
return qx.bom.element.AnimationJs.animate(el, desc, duration);
}
},
/**
* Starts an animation in reversed order. For further details, take a look at
* the {@link #animate} method.
* @param el {Element} The element to animate.
* @param desc {Map} The animations description.
* @param duration {Integer?} The duration in milliseconds of the animation
* which will override the duration given in the description.
* @return {qx.bom.element.AnimationHandle} AnimationHandle instance to control
* the animation.
*/
animateReverse : function(el, desc, duration) {
var onlyCssKeys = qx.bom.element.Animation.__hasOnlyCssKeys(el, desc.keyFrames);
if (qx.core.Environment.get("css.animation") && onlyCssKeys) {
return qx.bom.element.AnimationCss.animateReverse(el, desc, duration);
} else {
return qx.bom.element.AnimationJs.animateReverse(el, desc, duration);
}
},
/**
* Detection helper which detects if only CSS keys are in
* the animations key frames.
* @param el {Element} The element to check for the styles.
* @param keyFrames {Map} The keyFrames of the animation.
* @return {Boolean} <code>true</code> if only css properties are included.
*/
__hasOnlyCssKeys : function(el, keyFrames) {
var keys = [];
for (var nr in keyFrames) {
var frame = keyFrames[nr];
for (var key in frame) {
if (keys.indexOf(key) == -1) {
keys.push(key);
}
}
}
var transformKeys = ["scale", "rotate", "skew", "translate"];
for (var i=0; i < keys.length; i++) {
var key = qx.lang.String.camelCase(keys[i]);
if (!(key in el.style)) {
// check for transform keys
if (transformKeys.indexOf(keys[i]) != -1) {
continue;
}
// check for prefixed keys
if (qx.bom.Style.getPropertyName(key)) {
continue;
}
return false;
}
};
return true;
}
}
});