Performant Web Animations

The Search for 60fps

How to *not* do animations

jQuery.animate

$('.selector').animate({top: '100px'}, 2000);
var element = document.getElementsByClassName('selector')[0];
var current = element.style.top;
var goal = 100;
var step = (goal-current) / 2000;

var tick = function() {
    current += step;
    element.style.top = current + 'px';

    if (current < goal) {
        setTimeout(tick, 16);
    }
}

tick();

Two major issues!

vSync

Animating Layout Properties

vSync

Animating Layout Props

60fps means all of this needs to happen in less than ~16ms

How we *should* do animations

Simple Animations

transforms: position, scale, rotation

opacity

only requires compositing, done on the GPU

Simple Animations

transforms: position, scale, rotation

opacity

only requires compositing, done on the GPU

Complex Animations

Use JS to specify transforms,

and use RAF!

function mousedown(e) {
  lastEvent = e;
  requestAnimationFrame(tick);
}

function mousemove(e) {
  currentX += changeX;
  currentY += changeY;
   
  lastEvent = e;
}

function mouseup(e) { lastEvent = null; }

function tick() {
  box.style.transform = 'translate('+currentX+'px,
                        '+currentY+'px)';
  
  if (lastEvent) {
    requestAnimationFrame(tick);
  }
}

Complex Animations

Use JS to specify transforms,

and use RAF!

var position = 0;
var velocity = 0;
var acceleration = 1;

var ball = document.getElementById('ball');

function tick() {
  velocity += acceleration;
  position += velocity;
  
  position = Math.min(position, 180);
  
  if (position >= 180) {
    velocity *= -1;
  }
  
  ball.style.top = position + 'px';

  setTimeout(tick, 16);
}

tick();

Bad!

Complex Animations

Use JS to specify transforms,

and use RAF!

var position = 0;
var velocity = 0;
var acceleration = 1;

var ball = document.getElementById('ball');

function tick() {
  velocity += acceleration;
  position += velocity;
  
  position = Math.min(position, 180);
  
  if (position >= 180) {
    velocity *= -1;
  }
  
  ball.style.transform = 'translateY('+position+'px)';

  requestAnimationFrame(tick);
}

tick();

Good!

Conclusions

  • Know how the browser executes your animations
  • Prefer to animate things that only require compositing
  • Avoid animating things that modify layout
  • Don't use setTimeout / setInterval for animations

More Reading

Questions?

Thanks

Made with Slides.com