Yesterday Chris Heilmann wrote a post on the Mozilla blog about detecting and generating CSS animations using JavaScript. The article features a small example from myself demonstrating the rather verbose technique required to access a CSS animation with code.
Chris ends his article with the following:
I’d love to have a
CSSAnimations
collection for example where you could store different animations in JSON or as a string and have their name as the key. Right now, creating a new rule dynamically and adding it either to the document or append it to the ruleset seems to be the only cross-browser way. Thoughts?
This seemed like a great idea so I set about creating a small JavaScript shim to provide this interface.
CSS Animation Store
The idea is to create a simple interface for accessing CSS Animations from within JavaScript. This is something I’ve done a couple of times in the past with Morf.js and CSSA so had most of the code written already, it just needed wrapping up in the suggested JSON style interface that Chris described.
Download CSS Animation Store from GitHub
Here is the basic interface for the CSS Animation Store (for information on how the script works see below). Include the JavaScript just before the closing </html>
and it will expose a new global object called CSSAnimations
. The object contains each available CSS Animation currently available.
So, to get an animation named ‘spin’ you would do the following:
var spin = CSSAnimations.spin;
The variable spin
now holds an instance of a KeyframeAnimation
object, which has the following properties and functions:
keyframes
array ofKeyframeRule
objectsoriginal
gives access to the nativeWebKitCSSKeyframesRule
orMozCSSKeyframesRule
object this object wrapsgetKeyframeTexts()
returns an array of all available keyframe texts, e.g. ['0%', '50%', '100%']getKeyframe(text)
returns aKeyframeRule
based on the provided text, e.g.getKeyframe('0%')
setKeyframe(text, css)
sets the CSS for a keyframe the given text, e.g.setKeyframe('10%', {background: 'red', 'font-size': '2em'})
As you can see, a few of these methods/properties also deal with another type of object called KeyframeRule
. This is a wrapping around the WebKitCSSKeyframeRule
and MozCSSKeyframeRule
(note frame not frames). The KeyframeRule
object has the following properties:
css
object with the CSS for this keyframe, e.g.{background: 'red', 'font-size': '2em'}
keyText
the text name for this frame, e.g.10%
original
gives access to the nativeWebKitCSSKeyframeRule
orMozCSSKeyframeRule
object this object wraps
Examples of use
Getting the CSS for each frame in an animation
var spin = CSSAnimations.spin;
for(var i=0; i<spin.keyframes.length; i++)
console.log(spin.keyframes[i].css);
Adding/modifying a keyframe in an animation
var spin = CSSAnimations.spin;
spin.setKeyframe('10%', {background: 'red', 'font-size': '2em'});
Feedback
Let me know what you think in the comments or on GitHub, I’m also open to suggestions for modifications or additions!
Accessing/creating CSS Animations with native Javascript
Here’s a quick overview for those not wishing to use the CSS Animation Store, or those that want to know how it works under the hood.
Accessing CSS Animations
Accessing keyframe animations is done using the CSSOM. Here’s the function from my CSSA script that I use to access a given CSS Animation:
CSSAnimation.find = function(a) {
var ss = document.styleSheets;
for (var i = ss.length - 1; i >= 0; i--) {
try {
var s = ss[i],
rs = s.cssRules ? s.cssRules :
s.rules ? s.rules :
[];
for (var j = rs.length - 1; j >= 0; j--) {
if ((rs[j].type === window.CSSRule.WEBKIT_KEYFRAMES_RULE || rs[j].type === window.CSSRule.MOZ_KEYFRAMES_RULE) && rs[j].name == a){
return rs[j];
}
}
}
catch(e) { /* Trying to interrogate a stylesheet from another domain will throw a security error */ }
}
return null;
};
You can then use this in code like this:
var animation = CSSAnimation.find("spin"); // Get the animation named 'spin'
The returned object will either be of type WebKitCSSKeyframesRule
or MozCSSKeyframesRule
depending on the browser you’re using.
Creating CSS Animations
The only way I’ve found to create animations on the fly is a little hacky. It involves crafting the CSS string in code and either inserting it into the CSSOM or appending a style tag to the current HTML document.
Here’s how I do this in my library Morf.js:
// Adds the CSS to the current page
addKeyframeRule = function(rule) {
if (document.styleSheets && document.styleSheets.length)
// Insert the style into the first attached stylesheet
document.styleSheets[0].insertRule(rule, 0);
else
{
// No attached stylesheets so append to the DOM
var style = document.createElement('style');
style.innerHTML = rule;
document.head.appendChild(style);
}
}
Once you’ve crafted your CSS animation string you can then call the above function like this:
var css = '@-webkit-keyframes spin { ... }';
addKeyframeRule(css);
Pingback: yCoder » 通过JavaScript访问和修改CSS3动画
Pingback: 通过JavaScript访问和修改CSS3动画 |