Sunday, June 1, 2014

Web Animations - element.animate() is now in Chrome 36

Web Animations - element.animate() is now in Chrome 36

Animation on the web was once the province of JavaScript, but as the world moved to mobile, animations moved to CSS for the declarative syntax and the optimizations browsers were able to make with it. With 60fps on mobile always your goal, it makes sense to never step outside of what browsers know how to efficiently display.
More tools are appearing to make JavaScript-driven animations more efficient, but the holy grail is a unification of declarative and imperative animations , where the decision of how to write your animations is based on what’s the clearest code, not what is possible in one form and not in the other.
Web Animations stand to answer that call, and the first part of it has landed in Chrome 36 in the form of element.animate(). This new function lets you create an animation purely in JavaScript and have it run as efficiently as any CSS Animation or Transition (in fact, as of Chrome 34, the exact same Web Animations engine drives all of these methods)
The syntax is simple, and its parts should be familiar to you if you’ve ever written a CSS Transition or Animation:
element.animate([
  {cssProperty: value0},
  {cssProperty: value1},
  {cssProperty: value2},
  //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});
The biggest advantage of this new function is the elimination of a lot of awkward hoops we formerly had to jump through to get a smooth, jank-free animation.
As an example, for Santa Tracker last year, we wanted to have snow falling continuously, and we decided to animate it via CSS so that it could be done so efficiently.
However, we wanted to pick the snow’s horizontal position dynamically based on screen and events going on in the scene itself, and of course the height of the snow’s fall (the height of the user’s browser window) wouldn’t be known until we were actually running. This meant we really had to use CSS Transitions, as authoring a CSS Animation at runtime gets complex quickly (and hundreds of snowflakes means hundreds of new styling rules).
So we took the following approach, which should be familiar:
snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';
The key is in that 'wait a frame’ comment. In order to successfully start a transition, the browser has to acknowledge that the element is in the starting position. There are a few ways to do this. One of the most common ways is to read from one of the element properties that forces the browser to compute layout, thereby ensuring it knows that the element has a starting position before transitioning to the ending position. Using this method allows you to congratulate yourself on your superior knowledge of browser internals while still feeling dirty with every keystroke.
In contrast, the equivalent `element.animate()` call couldn’t be more clear, saying exactly what is intended:
snowFlake.animate([
  {transform: 'translate(' + snowLeft + 'px, -100%)'},
  {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
There are many more options. Just like with its CSS counterparts, Web Animations can be delayed and iterated:
snowFlake.animate([
  {transform: 'translate(' + snowLeft + 'px, -100%)'},
  {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
  duration: 1500,
  iterations: 10,
  delay: 300
});

No comments:

Post a Comment