Browser animation in 2017

動く・動かせ・動け!

動く

今できること

CSS Transitions

CSS Animations

CSS Transitions

A → B

CSS Animations

  • A → B → C
  • A → B → A
  • 繰り返し

x

(でもCSSTransitionGroupに注意)

4+ (transitions)

5+

1+

10+

3+ (transitions)

4+

Script animations

Web Animations API

Animating like you just don't care with Element.animate()

48+

36+

Priority: Medium

実装中

動かせ

動け

これからのアニメ

問題① フレームのアニメーション

問題① フレームのアニメーション

問題① フレームのアニメーション

問題① フレームのアニメーション

問題① フレームのアニメーション

問題① フレームのアニメーション

frames(n) (n ≥ 2)

55+

実装済み?
(昨日)

問題②Transitionの終わりを待つ

// Style:
// transition: opacity 1s

// transitionを発火する
elem.style.opacity = '0';
getComputedStyle(elem);

// 終わったら次の画面をactiveにする
elem.addEventListener('transitionend', evt => {
  if (evt.propertyName === 'opacity') {
    evt.target.remove();
    homeScreen.classList.add('active');
  }
});

/*
 * でも…
 */

button.addEventListener('focus', () => {
  // もしこれがmustacheのようなテンプレート仕組み…
  render();
});

問題②Transitionの終わりを待つ

transitionendが発火されないケース

  • 要素が消えた
  • 要素の親がdisplay:noneになった
  • transition-propertyからtransitionされているpropertyが消えた
  • transitionがそもそも生成されなかった
    (例:opacityが既に0になった場合)

問題②Transitionの終わりを待つ

transitioncancel 53+
transitionrun 53+
transitionstart 53+ 10
animationcancel 54+

問題②Transitionの終わりを待つ

Promise.all(
  elem.getAnimations().map(animation => animation.finished)
).then(() => {
  // アニメーション全部終わった。ハズ。
});
Element.getAnimations()

Nightly

問題③アニメーションがぶつかる

問題③アニメーションがぶつかる

問題③アニメーションがぶつかる

問題③アニメーションがぶつかる

Nightly

Canary
(Experimental web platform features)

'animation-composition'

CSS Animations Level 2
https://drafts.csswg.org/css-animations-2/#animation-composition

問題④スクロールに沿ってアニメーションしたい

問題④スクロールに沿ってアニメーションしたい

問題④スクロールに沿ってアニメーションしたい

問題④スクロールに沿ってアニメーションしたい

const animation = target.animate({ transform: 'scale(2)' },
                                 { duration: 1000,
                                   fill: 'both' });
animation.timeline =
  new ScrollTimeline({ scrollSource: elem });

問題④スクロールに沿ってアニメーションしたい

問題④スクロールに沿ってアニメーションしたい

問題⑤別のスレッドでアニメーションしたい

// twitter-header-animator.js

registerAnimator('twitter-header', class {
  animate(timelines, outputEffects) {
    const time = timelines[1].currentTime; // [0...timeRange]
    outputEffects[0].localTime = time;  // Sets the time used in the first output effect.
    outputEffects[1].localTime = Math.min(1, time * 10); // Clamps the input time range.
  }
});

// my-page.js

animationWorklet.import('twitter-header-animator.js').then( _ => {
  var anim = new WorkletAnimation('twitter-header',
    [
      new KeyFrameEffect(avatarEl,
                         { transform: [ 'translateX(100px)', 'translateX(0px)' ] },
                         { duration: 100, iterations: infinite }),
      new KeyFrameEffect(headerEl, { opacity: [ 0, 1 ] }, 100)
    ],	[
      document.timeline,
      new ScrollTimeline(scrollingElement, { timeRange: 100 })
    ]
  );
});

Browser animation in 2017 (Brian's fork)

By Brian Birtles

Browser animation in 2017 (Brian's fork)

  • 2,003