On Github elifitch / animation-talk
recruiting
Fun, frivolous, experiments like this guy
This isn't going to be super pracitcal "this is how you use this neat library" type stuff, there's lots of information out there on the interwebs for that, I'm going to focus more on when and why they should be considered, and relative strengths/weaknesses
This applies to most interactions, really.
Think changing the background on a ghost button, animating a button press to give the sense of 3d.
CSS makse such small changes really easy and quick to whip up, making carelessness easy too.
Most people have a good handle on this and just throw them in there willy nilly without regard for performance
Talk about the facebook study
Small % of users, 20-30 million
Hmm these appear to be the same but why is one choppy
WTAF is goon on here??
Layout is figuring out where everything is on the screen and how big it is.
Layout: Also if you're changing heights, widths etc can change the position of other elements it causes more layout changes and more and more and more and OH GOD
Images hard to see but the orange blocks represent browser thinky time
Blue is GPU doing its thing
See how one is way easier on the browser than another?
This is b/c one prop triggers layout while the other does not
Depends on size of paint area: ie fixed backgrounds cause janky scroll
Layers aren't free, layers aren't a magic bullet. They break sticky elements for example, b/c they fix relative to the layer, not relative to the viewport.
On older mobile devices, you can run out of GPU memory, and have a severe stutter as a result
width/height
top/right/bottom/left
padding
font-size
color
background
box-shadow
border-radius
opacity
scale
rotate
translate
Avoid layout changes, and if you have to make one, if you can isolate that element, good
Avoid continually repainting large areas (parallax for example)
Leverage transforms and opacity in creative ways to make up for other shit
I know which properties give the most performance now, I can optimize my CSS animations, why not use for everything.
When you think in terms of what CSS will let you do you will never fulfil your potential
This, as we will discuss later, also applies to any javascript object property
This, as we will discuss later, also applies to any javascript object property
Isn't shitty JS anim the whole reason CSS rose to prominence?
JS isn't necessarily janky. Poorly WRITTIen JS anims are janky.
Folks falsly conflate JS and JQ anims
With RAF "The browser can optimize concurrent animations together into a single reflow and repaint cycle
For example, JS-based animations synchronized with CSS transitions or SVG SMIL.
Also Animations in inactive tabs will stop, allowing the CPU to chill.
It's also synced with refresh rate so you won't drop frames
var opacity = 0; // runs every 16ms to try to achieve 60fps (1000ms/60 ~= 16ms). var fadeIn = setInterval(function() { if(opacity < 1) { element.style.opacity = (opacity += 0.05); } else { clearInterval(fadeIn) } }, 16);
// requestAnimationFrame: Attempts to run at 60fps based on // whether the browser is in an optimal state. var opacity = 0; var fadeIn = function() { if(opacity < 1){ window.requestAnimationFrame(fadeIn); element.style.opacity = (opacity += 0.05); } } fadeIn();
Just talking 2 easy things to have a big impact
JS performance could be a whole talk in and of itself
Remember how I said JS animation isn't janky, shitty JS animation is janky?
Theres some easy tips to improve your JS performance
As long as we're here, lets Not just talk anims, but also w/ events that trigger anims
var h1 = element1.clientHeight; // Read (measures the element) element1.style.height = (h1 * 2) + 'px'; // Write (invalidates current layout) var h2 = element2.clientHeight; // Read (measure again, so must trigger layout) element2.style.height = (h1 * 2) + 'px'; // Write (invalidates current layout) var h3 = element3.clientHeight; // Read (measure again, so must trigger layout) element3.style.height = (h3 * 2) + 'px'; // Write (invalidates current layout)
// Readenzie var h1 = element1.clientHeight; var h2 = element2.clientHeight; var h3 = element3.clientHeight; // Writenzie element1.style.height = (h1 * 2) + 'px'; element2.style.height = (h1 * 2) + 'px'; element3.style.height = (h3 * 2) + 'px';
especially bad w/ jQuery. Makes it so easy to read and write to the dom, that people do it willy nilly w/o regard for performance
Credit Wilson Page http://wilsonpage.co.uk/preventing-layout-thrashing/ be mindful of layout in JS too, CSS often triggered by JS Problem is, nobody actually writes code this way. Segue into workflow/library shit? You can use something like fastdom, or a dedicated anim library that includes batching as a performance enhancervar debounce = function(func, wait, immediate) { var timeout, result; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) result = func.apply(context, args); }; var callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) result = func.apply(context, args); return result; }; }; window.addEventListener('scroll', function(){ debounce(function(){ //cool animation },100) },false)
.logo { animation: myAnimation 2s linear forwards; } @keyframes myAnimation { 0% { opacity: 0; transform: scale(0, 0); } 25% { opacity: 1; transform: scale(1, 1); } 50% { transform: translate(0px, 0); } 100% { transform: translate(100px, 0); } }
So what happens when somebody wants the translate to take an extra 400ms?
You have to add 400ms to the duration and go back and recalc all the percentages relative to the new time and agh
It sucks, we've all had to do it, but it doesn't have to be this way
Managing CSS keyframes, especially when they get complex, can be hard, it can be time consuming.
Impedes experimentation.
And in the end, when you want to get creative, CSS animation is limiting(no independent transforms, different steps with different easing etc).logo { animation: myAnimation 2s linear forwards; } @keyframes myAnimation { 0% { opacity: 0; transform: scale(0, 0); } 25% { opacity: 1; transform: scale(1, 1); } 50% { transform: translate(0px, 0); } 100% { transform: translate(100px, 0); } }
var el = document.getElementsByClassName('logo') Velocity(el, { opacity: [1, 0], scale:[1, 0] },{ duration:500, easing: "linear" } ); Velocity(el, { translateY: '100px' },{ duration:1000, delay:500, easing: "linear" } );
var el = document.getElementsByClassName('logo') TweenLite.fromTo(el, .5, { opacity:0, scale:0, ease:"Linear.easeNone" },{ opacity:1, scale:1, ease:"Linear.easeNone", onComplete: function(){ TweenLite.to(el, 1, { delay:.5, y:100, ease:"Linear.easeNone" }); } } );
Expressed in terms of time, not percents more intutive
Performing multi anims on 1 element is easy, b/c instead of writing 1 super complex keyframes, you can just chain velocity or GSAP calls (come in, drop down)
Both of these examples show how you can feed in start values for the element different from its resting CSS which can be useful
Easier than wrangling with keyframes, and yeah, probably easier than rolling your own RAF loops.
R/yy makes it super easy to go back to the original position, w/ CSS you have to make the anim go to 50%, and build it back to orig yourself, its unintuitive
Sequencing: instead of specifying a huge keyframes you can just chain anims together. If you want to change one, you can change the ONE. Doesn't screw up the maths for the whole thing
Last two only GSAP
If you're making a super super complex animation(10+ seconds long), storing it in a timeline means you can scrub to different parts to experiment, rather than waiting until the end every time you iterate
Allows you to easily breathe life into static elements
Animation by its very nature is iterative and experimental
1) too many timers firing at once reduces frame rates due to the browser’s overhead of maintaining them
2) improperly marking the time at which your animation begins results in dropped frames (usually you have the animation start when you click the button, but due to a myriad of factors like CPU overhead, other JS logic at the same time, etc) can cause a delay in when you start to see the anim, dropping early frames.
Caching property values across chained calls in order to minimize the occurrence of DOM querying (which is the Achilles' heel of performant DOM animation).
Caching unit conversion ratios (e.g. px to %, em, etc.) across sibling elements in the same call.
Kind of like a debounce, function only runs when nec. Skipping style updating when updates would be visually imperceptible.
You could write these optimizations into your own hand crafted animation code, but then A. your code becomes harder to manage, and B. you end up creating an animation library yourself.
It can do more. A lot more. It can tween any property of any javascrpit object. BIG distinction. Means that it's not just for UI animation, but for WebGL, canvas, games, and other shit my puny human brain can't even dream up
Timlining both good for workflow and make it easier to have animations overlap, sequence, etc
I'm unsure as to why, but it performs a smidge better than velocity in ultra high stress situations
TweenLite & CSSPlugin ~60kb
Have to pay to use it in a product
For the fun and the frivolous
It's a UI animation tool, well suited for it, and w/o the bloat/features of GSAP
~30kb, all in
At least to me, it makes a bit more sense. Take sequencing for example, you just follow it with another .velocity, don't need to mess around w/ callbacks
this is huge. The examples we showed thusfar was to how to use velocity w/o jquery. However, if you use jquery you can literally just include velocity, and do a find/replace for .animate, and you've gotten a massive, free performance boost
Julian is a great guy, loves PRs, easy to get involved in community
Each velocity call returns a promise object
Conclusion