This was from a talk I gave at New York Front End Coders in July 2013 on how to create random CSS Animations.
CSS Keyframe Animations are definitions in CSS that outline the CSS properties to be animated and the points in time during the life of the animation that these animations should be achieved. This can lead to huge amounts of CSS when trying to make something appear random.
This talk sought to explain how randomisation (of a sort) was achieved. Hopefully the slides themselves can communicate this.
9. SEPARATION OF CONCERNS
Don't write HTML Elements with JavaScript
Use CSS to change appearance
Use JavaScript for the rest
10.
11. THE APPROACH (AGAIN)
Respect the separation of concerns
Minimal interaction with the DOM
Keep it "jank"-free
Can we achieve randomised CSS animations with this
approach?
22. ATTACHING A DEFINED KEYFRAME ANIMATION
.classWithAnimation {
animation: myAnimationName 1.2s linear 0s infinite;
}
23. ... WITH PREFIXES
.classWithAnimation {
-webkit-animation: myAnimationName 1.2s linear 0s infinite;
-moz-animation: myAnimationName 1.2s linear 0s infinite;
animation: myAnimationName 1.2s linear 0s infinite;
}
24. SHORTHAND PROPERTIES EXPANDED
/* shorthand */
.bubble {
animation: myAnimationName 1.2s linear 0s infinite;
}
/* expanded */
.bubble {
animation-name: myAnimationName;
animation-duration: 1.2s;
animation-timing-function: linear;
animation-delay: 0s;
animation-iteration-count: infinite;
}
and that's just some of them
… at MDNthere are more
26. ARE WE THERE YET?
CSS Keyframe Animations, they:
define a start
… the inbetween frames
… and the end?
27.
28. THE END IS NOT THE END
"omit the to or 100% declaration from the
@keyframe…"
"then you call the animation on the progress
bar…"
"and just like that, the progress bar will
animate itself up to the value set by the inline
style."
Chris Coyer's post on animating to an inline style
29.
30. "omit the to or 100% declaration from the
@keyframe…"
@keyframes myAnimationName {
0% {background-position: 0 0;}
}
31. "…then you call the animation on the progress
bar…"
.bubble {
animation: myAnimationName 1.2s linear 0s infinite;
}
32. "…and just like that, the progress bar will
animate itself up to the value set by the inline
style."
<div id="bubble_0" class="bubble" style="background-position: -162px 0;"></div>
33.
34. DOES IT NEED TO BE INLINE?
What if the properties were set in a class ruleset?
/* css */
@keyframes myAnimationName {
0% {background-position: 0 0;}
}
.bubble {
animation: myAnimationName 1.2s linear 0s infinite;
}
.background-move {
background-position: -162px 0;
}
Then the class was dynamically applied to the DOM Element?
<!-- html -->
<div id="bubble_0" class="bubble background-move"></div>
41. GAME ON
When the page loads we:
1. Load custom classes "Bubble" and "BubbleController"
2. BubbleController puts all ".bubble" divs into an Array
3. It then makes two 'object pools'
4. One has "Bubble" instances, the other is ids from each div in
the Array
42. OBJECT POOLS ON HTML5ROCKS
Colt McAnlis's post on Object Pools in JS
43. GAME ON…
Then:
1. BubbleController runs a loop creating setTimeouts at
+200ms
2. The interval calls BubbleController's 'createBubble' method
3. This method pops a Bubble instance from its pool
4. It also pops an id from the id pool
5. It creates a listener for completion of the Bubble's 'init'
method
6. It creates a listener for completion of the Bubble's 'hide'
method
7. It runs the Bubble's 'init' method, with the id property
44. OBJECT POOL CODE IN BUBBLECONTROLLER
// `bubbles` is an Array of Dom Elements
// `bubbleClass` is Bubble
function createObjectPools (bubbles, bubbleClass) {
var j = bubbles.length;
var bubbleArgs = { delegateName: NAME };
while (j--) {
// populate the individual bubble's ids into an Array
idPool[j] = bubbles[j].id;
// use an Object Pool to create enough instances to control each bubble
bubblePool[j] = new bubbleClass(bubbleArgs);
}
}
45. 'CREATEBUBBLE' METHOD IN
BUBBLECONTROLLER
function createBubble () {
// get new bubble instance id form the pools
var bubble = bubblePool.pop();
var id = idPool.pop();
// listen for the end of the new bubble's init phase
$.subscribe(NAME + EVENTS.INIT + STATUS.COMPLETE + id, bubbleInitCompleteHandle
// call init on the bubble instance
bubble.init({ id: id });
}
46.
47. GAME ON… ALMOST THERE
Finally, the Bubble's 'init' method:
1. The Bubble instance gets the DOM Element via the id
2. Bubble creates a listener for the 'animationend' event
3. It then gets a random class from each sub-Array in
ANIMATION_CLASSES
4. It saves these as a String, but doesn't set its className
5. It fires off its 'init complete' Event
6. BubbleController reacts to this and calls
requestAnimationFrame.
7. requestAnimationFrame calls the Bubble instances 'show'
method
8. The 'show' method attaches the classlist, starting the
animation
51. 'SHOW' METHOD IN BUBBLE
Bubble.prototype.show = function () {
// appending the classes makes the bubble appear and the animation run
this.node.className = this.classList;
};
52. GAME OFF
'animationend' event
1. The Bubble reacts to the DOM Element's 'animationend'
event
2. It changes the className of the DOM Element to "splat"
3. It runs its 'hide' method and fires off 'hide complete'
4. Inside the 'hide complete' Event is the id as a String
5. BubbleController reacts to this
6. It 'pools' the Bubble instance and 'pools' the id
7. It then runs its 'createBubble' method to start all over again
53. RE-'POOLING' THE BUBBLE AND ID IN
BUBBLECONTROLLER
function bubbleAnimationCompleteHandler (e, bubble, id) {
// add the completed bubble and its id back into the pools
bubblePool.unshift(bubble);
idPool.unshift(id);
createBubble();
}
55. TIME ESCAPES ME
The bubbles are done with :before and :after
They're webfonts - that's a story in itself
You can pause the bubbles
'animation-timing-function' easing is done with cubic-
beziers
THEY'RE CLICKABLE!