RANDOMISING CSS
ANIMATIONS
ADAM BANKIN
Front End Engineer at Shutterstock
14 years experience with HTML, CSS and JS
AUSTRALIAN
(z === "zed"); // true
"ize".replace(/z/, "s");
(r === "ahhhhhh"); // true
$("#shrimp").on("barbie", function (...
RANDOMISING CSS ANIMATIONS
Why? Is this difficult?
Shutterstock labs home page
THE APPROACH
Respect the separation of concerns
Minimal interaction with the DOM
Keep it "jank"-free
DAFT JANK
Addy Osmani's post on jank busting
SEPARATION OF CONCERNS
Don't write HTML Elements with JavaScript
Use CSS to change appearance
Use JavaScript for the rest
THE APPROACH (AGAIN)
Respect the separation of concerns
Minimal interaction with the DOM
Keep it "jank"-free
Can we achiev...
HTML
Keep it simple
PREDEFINE YOUR DOM ELEMENTS
<div id="bubble_source">
<div id="bubble_0" class="bubble"></div>
<div id="bubble_1" class="bu...
CSS
The syntax of CSS Keyframe Animations
AT-RULE AND NAME
@keyframes myAnimationName {...}
… WITH PREFIXES
@-webkit-keyframes myAnimationName {...}
@-moz-keyframes myAnimationName {...}
@keyframes myAnimationName ...
WITH KEYFRAMES
@keyframes myAnimationName {
from {
background-position: 0 0;
}
to {
background-position: -162px 0;
}
}
MDN...
CHOOSE THE RIGHT PROPERTIES TO ANIMATE
top/left | translate
Paul Irish's post on using translate instead of top/left
WITH PERCENTAGE-BASED KEYFRAMES
@keyframes myAnimationName {
0% {
background-position: 0 0;
}
100% {
background-position: ...
MIXED VALUES IN KEYFRAMES
@keyframes myAnimationName {
0% {
background-position: 0 0;
}
23% {
opacity: 0;
background-posit...
TARGETING PREFIXED PROPERTIES
@-webkit-keyframes myAnimationName {
0% {-webkit-transform-origin: 0 0;}
100% {-webkit-trans...
ATTACHING A DEFINED KEYFRAME ANIMATION
.classWithAnimation {
animation: myAnimationName 1.2s linear 0s infinite;
}
... WITH PREFIXES
.classWithAnimation {
-webkit-animation: myAnimationName 1.2s linear 0s infinite;
-moz-animation: myAnim...
SHORTHAND PROPERTIES EXPANDED
/* shorthand */
.bubble {
animation: myAnimationName 1.2s linear 0s infinite;
}
/* expanded ...
*AHEM*… PREFIXED
/* let's now call it 'bubble' */
.bubble {
-webkit-animation-name: myAnimationName;
-webkit-animation-dur...
ARE WE THERE YET?
CSS Keyframe Animations, they:
define a start
… the inbetween frames
… and the end?
THE END IS NOT THE END
"omit the to or 100% declaration from the
@keyframe…"
"then you call the animation on the progress
...
"omit the to or 100% declaration from the
@keyframe…"
@keyframes myAnimationName {
0% {background-position: 0 0;}
}
"…then you call the animation on the progress
bar…"
.bubble {
animation: myAnimationName 1.2s linear 0s infinite;
}
"…and just like that, the progress bar will
animate itself up to the value set by the inline
style."
<div id="bubble_0" cl...
DOES IT NEED TO BE INLINE?
What if the properties were set in a class ruleset?
/* css */
@keyframes myAnimationName {
0% {...
RULESET AS INLINE STYLE
/* Keyframe Animation definitions */
@-webkit-keyframes lightBlue {
0% {
color: #2ed0e5;
-webkit-t...
JAVASCRIPT
Make it work
WHAT DOES JAVASCRIPT GIVE US?
requestAnimationFrame/cancelAnimationFrame methods
Event-type "animationend"
… WITH PREFIXES
requestAnimationFrame, msRequestAnimationFrame,
mozRequestAnimationFrame,
webkitRequestAnimationFrame, oRe...
CLASSY JAVASCRIPT
var ANIMATION_CLASSES = [
// colors
['color_dark_red', 'color_red', 'color_yellow', 'color_green', 'col
...
GAME ON
When the page loads we:
1. Load custom classes "Bubble" and "BubbleController"
2. BubbleController puts all ".bubb...
OBJECT POOLS ON HTML5ROCKS
Colt McAnlis's post on Object Pools in JS
GAME ON…
Then:
1. BubbleController runs a loop creating setTimeouts at
+200ms
2. The interval calls BubbleController's 'cr...
OBJECT POOL CODE IN BUBBLECONTROLLER
// `bubbles` is an Array of Dom Elements
// `bubbleClass` is Bubble
function createOb...
'CREATEBUBBLE' METHOD IN
BUBBLECONTROLLER
function createBubble () {
// get new bubble instance id form the pools
var bubb...
GAME ON… ALMOST THERE
Finally, the Bubble's 'init' method:
1. The Bubble instance gets the DOM Element via the id
2. Bubbl...
'INIT' METHOD IN BUBBLE
Bubble.prototype.init = function (args) {
// add inited variables
this.id = args.id;
this.node = d...
RANDOMISING THROUGH THE
ANIMATION_CLASSES ARRAY
function setClassList (instance) {
var j = ANIMATION_CLASSES.length;
while...
CALLING REQUESTANIMATIONFRAME IN
BUBBLECONTROLLER
function bubbleInitCompleteHandler (e, bubble) {
$.unsubscribe(e.type, b...
'SHOW' METHOD IN BUBBLE
Bubble.prototype.show = function () {
// appending the classes makes the bubble appear and the ani...
GAME OFF
'animationend' event
1. The Bubble reacts to the DOM Element's 'animationend'
event
2. It changes the className o...
RE-'POOLING' THE BUBBLE AND ID IN
BUBBLECONTROLLER
function bubbleAnimationCompleteHandler (e, bubble, id) {
// add the co...
SO!!!
Did it work?
Labs home page
TIME ESCAPES ME
The bubbles are done with :before and :after
They're webfonts - that's a story in itself
You can pause the...
THANKS!
abankin@shutterstock.com
@adambankin
DID I MENTION WE'RE
HIRING?!
Randomising css animations
Randomising css animations
Randomising css animations
Randomising css animations
Randomising css animations
Randomising css animations
Randomising css animations
Randomising css animations
Randomising css animations
Randomising css animations
Upcoming SlideShare
Loading in …5
×

Randomising css animations

3,582 views

Published on

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.

Published in: Technology, Business
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
3,582
On SlideShare
0
From Embeds
0
Number of Embeds
5
Actions
Shares
0
Downloads
19
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Randomising css animations

  1. 1. RANDOMISING CSS ANIMATIONS
  2. 2. ADAM BANKIN Front End Engineer at Shutterstock 14 years experience with HTML, CSS and JS
  3. 3. AUSTRALIAN (z === "zed"); // true "ize".replace(/z/, "s"); (r === "ahhhhhh"); // true $("#shrimp").on("barbie", function () { console.error("racial stereotype"); console.error("and frankly, I'm offended"); return false; });
  4. 4. RANDOMISING CSS ANIMATIONS Why? Is this difficult?
  5. 5. Shutterstock labs home page
  6. 6. THE APPROACH Respect the separation of concerns Minimal interaction with the DOM Keep it "jank"-free
  7. 7. DAFT JANK Addy Osmani's post on jank busting
  8. 8. SEPARATION OF CONCERNS Don't write HTML Elements with JavaScript Use CSS to change appearance Use JavaScript for the rest
  9. 9. 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?
  10. 10. HTML Keep it simple
  11. 11. PREDEFINE YOUR DOM ELEMENTS <div id="bubble_source"> <div id="bubble_0" class="bubble"></div> <div id="bubble_1" class="bubble"></div> <div id="bubble_2" class="bubble"></div> <div id="bubble_3" class="bubble"></div> <div id="bubble_4" class="bubble"></div> <div id="bubble_5" class="bubble"></div> <div id="bubble_6" class="bubble"></div> … <div id="bubble_15" class="bubble"></div> </div> HTML… Done
  12. 12. CSS The syntax of CSS Keyframe Animations
  13. 13. AT-RULE AND NAME @keyframes myAnimationName {...}
  14. 14. … WITH PREFIXES @-webkit-keyframes myAnimationName {...} @-moz-keyframes myAnimationName {...} @keyframes myAnimationName {...}
  15. 15. WITH KEYFRAMES @keyframes myAnimationName { from { background-position: 0 0; } to { background-position: -162px 0; } } MDN has a list of animatable properties
  16. 16. CHOOSE THE RIGHT PROPERTIES TO ANIMATE top/left | translate Paul Irish's post on using translate instead of top/left
  17. 17. WITH PERCENTAGE-BASED KEYFRAMES @keyframes myAnimationName { 0% { background-position: 0 0; } 100% { background-position: -162px 0; } }
  18. 18. MIXED VALUES IN KEYFRAMES @keyframes myAnimationName { 0% { background-position: 0 0; } 23% { opacity: 0; background-position: -162px 0; } 100% { opacity: 1; } }
  19. 19. TARGETING PREFIXED PROPERTIES @-webkit-keyframes myAnimationName { 0% {-webkit-transform-origin: 0 0;} 100% {-webkit-transform-origin: 25px 0;} } @-moz-keyframes myAnimationName { 0% {-moz-transform-origin: 0 0;} 100% {-moz-transform-origin: 25px 0;} } @keyframes myAnimationName { 0% {transform-origin: 0 0;} 100% {transform-origin: 25px 0;} }
  20. 20. ATTACHING A DEFINED KEYFRAME ANIMATION .classWithAnimation { animation: myAnimationName 1.2s linear 0s infinite; }
  21. 21. ... 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; }
  22. 22. 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
  23. 23. *AHEM*… PREFIXED /* let's now call it 'bubble' */ .bubble { -webkit-animation-name: myAnimationName; -webkit-animation-duration: 1.2s; -webkit-animation-timing-function: linear; -webkit-animation-delay: 0s; -webkit-animation-iteration-count: infinite; }
  24. 24. ARE WE THERE YET? CSS Keyframe Animations, they: define a start … the inbetween frames … and the end?
  25. 25. 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
  26. 26. "omit the to or 100% declaration from the @keyframe…" @keyframes myAnimationName { 0% {background-position: 0 0;} }
  27. 27. "…then you call the animation on the progress bar…" .bubble { animation: myAnimationName 1.2s linear 0s infinite; }
  28. 28. "…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>
  29. 29. 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>
  30. 30. RULESET AS INLINE STYLE /* Keyframe Animation definitions */ @-webkit-keyframes lightBlue { 0% { color: #2ed0e5; -webkit-transform: translate(0, 50px) scale(.2, .2); -webkit-transform-origin: 20px 0; } 14% { color: #2ed0e5; -webkit-transform: translate(0, -100px) scale(.3, .3); -webkit-transform-origin: 43px 0; } } @-moz-keyframes lightBlue { 0% { color: #2ed0e5; -moz-transform: translate(0, 50px) scale(.2, .2); -moz-transform-origin: 20px 0; } 14% { color: #2ed0e5; -moz-transform: translate(0, -100px) scale(.3, .3); -moz-transform-origin: 43px 0; } } @keyframes lightBlue { 0% { color: #2ed0e5;
  31. 31. JAVASCRIPT Make it work
  32. 32. WHAT DOES JAVASCRIPT GIVE US? requestAnimationFrame/cancelAnimationFrame methods Event-type "animationend"
  33. 33. … WITH PREFIXES requestAnimationFrame, msRequestAnimationFrame, mozRequestAnimationFrame, webkitRequestAnimationFrame, oRequestAnimationFrame animationend, MSAnimationEnd, webkitAnimationEnd, oAnimationEnd
  34. 34. CLASSY JAVASCRIPT var ANIMATION_CLASSES = [ // colors ['color_dark_red', 'color_red', 'color_yellow', 'color_green', 'col // translations ['translateA', 'translateB', 'translateC', 'translateD', 'translate // origins ['originA', 'originB', 'originC', 'originD', 'originE', 'originF'], // durations ['time_1500', 'time_1800', 'time_2000', 'time_2500', 'time_2700'], // easings ['easing_1', 'easing_2', 'easing_3'], // names ['light_blue', 'mid_blue'] ];
  35. 35. 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
  36. 36. OBJECT POOLS ON HTML5ROCKS Colt McAnlis's post on Object Pools in JS
  37. 37. 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
  38. 38. 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); } }
  39. 39. '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 }); }
  40. 40. 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
  41. 41. 'INIT' METHOD IN BUBBLE Bubble.prototype.init = function (args) { // add inited variables this.id = args.id; this.node = doc.getElementById(args.id); this.$node = $(this.node); this.classList = 'bubble on'; // add listeners addListeners(this); setClassList(this); $.publish(this.delegateName + EVENTS.INIT + STATUS.COMPLETE + this.id, [this]); };
  42. 42. RANDOMISING THROUGH THE ANIMATION_CLASSES ARRAY function setClassList (instance) { var j = ANIMATION_CLASSES.length; while (j--) { instance.classList += (' ' + randomValue(ANIMATION_CLASSES[j])); } } function randomValue (arr) { var length = arr.length; var idx = (Math.random() * length) | 0; return arr[idx]; }
  43. 43. CALLING REQUESTANIMATIONFRAME IN BUBBLECONTROLLER function bubbleInitCompleteHandler (e, bubble) { $.unsubscribe(e.type, bubbleInitCompleteHandler); win.requestAnimationFrame(function () { bubble.show(); }); }
  44. 44. 'SHOW' METHOD IN BUBBLE Bubble.prototype.show = function () { // appending the classes makes the bubble appear and the animation run this.node.className = this.classList; };
  45. 45. 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
  46. 46. 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(); }
  47. 47. SO!!! Did it work? Labs home page
  48. 48. 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!
  49. 49. THANKS! abankin@shutterstock.com @adambankin DID I MENTION WE'RE HIRING?!

×