ブラウザーに優しくして、
アニメーションを滑らかに

Brian Birtles, Mozilla Japan

html5j October 2014, Tokyo

Animation is awesome…

Source: Christopher Price 2013, http://topherchris.com/post/55109717733

Animation is awesome…

Source: icanhasGIF.com
windfinder.com
earth.nullschool.net
healthmap.org/ebola/
ebolavideo.org

Animation is awesome?

HTC J 端末上の Firefox と Chrome で再生したアニメーション
最適化されていない
display:noneを利用

display:noneを利用

* Average result after 3~5 runs. Higher numbers are better.
ブラウザー 最適化されていない display:noneを利用 平均向上
Firefox 34 25.6fps 29fps 3.4fps / 13%
Chrome 36 5.1fps 12.5fps 7.4fps / 145%
IE 11 4.8fps 7.8fps 3.0fps / 63%
display:noneを利用して、レンダーツリーから要素を除去してみる
parapara.mozlabs.jp
Firefoxのプロファイラー
Chromeのプロファイラー

Reflow logging in Firefox

リフローさせるプロパティ

* このテストケースのプロフィール調査の結果。
プロパティ リフローさせる?*
Firefox 34 Chrome 36 IE 11
margin-left
left (position: relative)
left (position: absolute)
transform
margin-top
transform

リフローを避ける

top/left/margin-topなどよりtransformを使ってみる
position:absoluteなどの要素をアニメーションしてみる
coloropacityなどの配置と無関係のプロパティを使ってみる
font-sizeよりtransform: scaleをアニメーションしてみる

ブラウザーって怠け者

ブラウザーが起きてしまう処理

  • window.getComputedStyle(elem).color → スタイルの再算出 (ブラウザー次第?)
  • window.getComputedStyle(elem).width, elem.offsetTop, elem.getClientRects()など → リフロー

こんなコードはやめましょう


for (var i = 1; i < containerElem.children.length; i++) {
  containerElem.children[i].style.top =
    containerElem.children[i-1].offsetTop + 10 + "px";
}
          

リフローを避ける

* Average result after 3~5 runs of test A and test B. Results for Firefox were particularly variable but were generally only slightly faster since the test animates the top property which does not trigger reflow in Firefox.
ブラウザー リフローさせる リフローをさせない 平均向上
Firefox 34 42.1fps* 45.8fps* 3.7fps / 9%
Chrome 36 10.5fps 23.2fps 12.7fps / 120%
IE 11 8.2fps 19.1fps 10.9fps / 132%
算出されたスタイル(特に配置に関わるプロパティ)を読み込むのを減らしてみる

描画コスト

描画の領域
描画の重さ

Paint flashing (Firefox)

Paint rectangles (Chrome)

Paint flashing

重い描画

  • box-shadow
  • border-radius
  • SVGのフィルター効果…
<feGaussianBlur>stdDeviationをアニメーションするなら → 33fps
ぼやけしたコピーのtransform(scale)をアニメーションするなら → 49fps
重い効果をより簡単なのに置き換えてみる

事前描画

ブラウザー <iframe src="svg"> <img src="png">
Firefox 34 1.9 fps 49.5 fps
Chrome 36 11.18 fps 49.7 fps
IE 11 5.8 fps 50.9 fps
重いリソースを事前描画してみる

事前描画

* 描画欠陥
ブラウザー <iframe src="svg"> <img src="svg"> <img src="png">
Firefox 34 1.9 fps 49.1 fps 49.5 fps
Chrome 36 11.18 fps 13.0 fps* 49.7 fps
IE 11 5.8 fps 15.5 fps 50.9 fps
SVG画像を埋め込むとき、<iframe>(又<object><embed>など)より、<img>を使ってみる

レイヤー化されたコンテンツって?

Animated transform
Animated opacity
3D transform

レイヤーの調査

  • Firefox: about:config
    layers.draw-bordersをtrueに
    (layers.offmainthreadcomposition.enabledfalseの場合、それをtrueに設定してからブラウザーを再起動する必要ある)
  • Chrome: DevConsole → Rendering → Show composited layer borders

レイヤーの調査

レイヤーの調査

Animated transform
Animated opacity
3D transform

レイヤーとCSS Transitions

レイヤーとJavascript アニメーション

アニメーションを動かす

will-changeに助かる

  • will-change:<property>
    • 例:will-change:transform
  • will-change:scroll-positionなども
  • transform:translateZ(0)
  • Firefox: about:configlayout.css.will-change.enabledをtrueに
    (来週デフォルトになる?)

ためらっているブラウザー

コンポジター上のアニメーション

スクリプト x コンポジター

スクリプト (GSAP)
CSS

速いことは速いんだが…

  • コンポジターでできるアニメション? (transform, opacity)
  • 対応するプラットフォーム? (例: Firefox OS)
    (layers.offmainthreadcomposition.async-animations → true)
  • 他の条件? (例: top/leftもアニメーションされている?)
  • ブラウザーのアニメーション? (例: CSS Animations)

スクリプトはダメ?


// Web Animations API! \o/
elem.animate({ transform: 'rotate(360deg)' },
             { duration: 1200,
               iterations: Infinity });
          
  • Chrome 36

Web Animations 実装中