「Element.animate」って?その魅力、欠点、使い道を説明! | from hacks.mozilla.org

法律: IT 映像制作 アニメ アニメーション ウェブ制作 オープンソース フノス(訳者)

By  Brian Birtles

 2016年8月3日投稿

 

  Firefox 48はElement.animate() APIに対応しました。これにより、JavaScriptでDOM要素を設定して、アニメを作ることが可能になったのです。

  これを好機と捉えるか、どうでもよいことと捉えるかはあなた次第ですが、アニメーションライブラリにまた1つ選択肢が増えたことに変わりはありません。
 この記事では、Element.animate()を使うことで何が作れるかということを説明していきます。

 

 パフォーマンスについて

  Element.animate() はウェブ・アニメーションAPI第一の設定項目です。もちろん、firefoxはこれに対応しています。アニメーションの同期性能、結合やモーフィング、CSSで他にも細工ができることなど、良質な機能がいくつもありますが、その中でも、パフォーマンスの高さには目を見張るものがあります。

  もしかしたら、JavaScript一本ではできなかった、引っ掛かりのないアニメーションをElement.animate()を使うことで、実現できるかもしれません。
 

  信じられないという方は、こちらのデモをご覧ください。

  左側がJavaScriptだけで作ったアニメーション、右側がElement.animate()で作ったアニメーションです。
  JavaScriptで作ったアニメーションのほうが、パフォーマンスが落ちやすいのがわかりますか。
 

  これが、JavaScriptアニメーションとElement.animate()の違いです。詳しいことについては我々がまとめたデモで確認できます。


 

   パフォーマンスといえば、変な噂が飛び交っていますね。
  「CSSアニメーションはGPUを食う」などという情報を先んじて受け取っていた方は、「軽いとかいうけど、信用はできない」と身構えているかもしれません。今日はその誤解を解きたいんですよ。

  それでは、Element.animate()の動作がなぜ速く、そして、アニメーションが遅くなる理由があるとしたら、それはどこなのかを説明しましょう。


 

 アニメーションは玉ねぎ(ケーキ、そしてパフェ)のように 

  ブラウザはコマを更新していくたびに、2つのことを行っています。
  1つ目は、ページにある要素のレイアウトを算出すること。
 2つ目は、算出したレイアウトを表示することです。

  アニメーションを負担なく再生したいのなら、コマごとに発生する「レイアウトの再算出」を少なくすればよいのです。

  「animateプロパティはレイアウトを更新しない」という話においては本当です。
  そして、賢いクリエイターはこの性質を利用して、animateプロパティを使いこなします。

(まったく別の事例ですが、色指定をcolorプロパティに任せると、「色」のレイアウトを再算出をなくすことができ、ページの読み取り速度が向上することは、有名ですよね。)
 


  たとえば、古典的な技法ですが、1つの背景のなかで、キツネ1匹を描いたセルを移動させて、「飛んでいる」ことを伝えるとします。
(もちろん、セルを使わずに、絵や写真を切り取って、背景の中で動かす技法も存在しますが少しマイナーです。)

 このようなアニメーションは、animateプロパティの
 transform(移動)とopacity(透明度=セル)を使って作成できます。

 背景の中でセルを動かしているだけのアニメーション

  

 


  数年前、ブラウザでもようやく、アニメを背景と動画に分けて処理できるようになりました。

  これにより、上のアニメのような、背景が動いていない映像でも、動いているキャラクターの部分だけを計算すれば、十分に再生が可能です。その分、GPUの消費も大幅に抑えられます。

  それでは、背景と動画の両方が動いていた場合はどうするのでしょう。その時は、GPUが3D処理を開始して、レイヤーごとに再計算の必要がない部分を検出して、ブラウザの処理を軽減するようになっています。

  アニメの処理のほとんどは、GPUに任せることができるのです。

  ブラウザでアニメーションを円滑に再生するには、それぞれのコマを16ミリ秒で更新していくとよいでしょう。
  なぜなら、ブラウザはなるべく、ディスプレイと同じレート(通常60Hz)でスクリーンを更新しようとするからです。

 

 ヒント:FirefoxのPaint Flashing Tool やChromeのPaint Rectanglesを使っている人は、レイヤー機能が使えているかどうかをチェックできます。もし、animating要素が検出されなかった場合には、何も描画できないからです。

レイヤーが発見されれば、Firefoxの場合、configページからlayers.draw-bordersを設定できます。Chromeの場合、レンダリングタブから「Show layer borders(レイヤーの境界線を表示)」を選択できます。

 
 

  レイヤーはすごい!みんなで使える!どんどん使おう!

  言いたいことわかりますね?実際レイヤーは素晴らしい。
  ブラウザをフル活用して、あなたのページコンテンツを充実させられます。(例:mille crêpe cake

  しかし、欠点はあります。

  まずレイヤーを使うと、ブラウザがすべての要素を認識して表示するまでに、だいぶメモリーを消費します。
  ユーザーからは他のレイヤーが重なって見えない部分も、ブラウザ側が描画してしまうからです。

  さらにレイヤーがあまりにも多すぎると、描画に時間がかかります。その処理が手間取ることから、アニメーションが遅くなってしまう場合もあるのです。

  なので、レイヤーは必要最低限にとどめておくことが大切です。
  先程の例で、transformやopacityがきちんと動いたのは、レイヤーが少なかったおかげともいえます。
 

  それから、まずブラウザがレイヤーに対応していないと、アニメがきちんと読み込まれず、ページの表示が遅くなる原因になります。

  レイヤーでアニメーションを表示する際には、レイヤーに対応していないブラウザのことも考慮して、再生前に警告を出しましょう。

  非対応のブラウザに再生させると、ブラウザがすべてのレイヤーのレイアウトを全力で再計算し続けるので、クラッシュを起こしやすくなります。自動再生はやめましょう。

  再生の前に1段階、念のためにブロックを設けます。これはマナーですね。(守っておくのがアニメを最も問題なく再生する早道です。)

  そのお知らせをブラウザに表示させるのに、will-changeというプロパティが使えます。これでアニメ再生のプランを設定してください。
 

  たとえば、クリックするとドロップダウンメニューが出てくるボタンってよくありますよね。

 こんなボタンです

 試してみる

  これを参考にして、ブラウザにレイヤーに関するメニューを作ってみましょう。
 

nav {

  transition: transform 0.1s;

  transform-origin: 0% 0%;

  will-change: transform;

nav[aria-hidden=true]

  transform: scaleY(0); 


  しかし、このお知らせも、あんまり乱発はしないほうがよいでしょう。オオカミ少年みたいになってしまいます。お知らせは、サイトに訪れて最初ぐらいに設定するか、あとは表示に時間がかかりそうなくらい大きなファイルを再生するときなど、適宜がよろしいですね。

  設定するときには、ウェブコンソールを使うと便利です。will-changeを使うには次のようにするとよいでしょう。
 

 [スクリーンショット]ウェブコンソールでwill-chnageを設定する



 

 animateを気軽に使おう

  さて、レイヤーの性質と使い道がわかったところで、Element.animate()の良い面に光を当てていきましょう。
 これまでに説明してきたanimateの性質は次の3つですね。

  ところで、ブラウザは結局のところ1コマを最速何秒で処理できるのでしょうか。
  ブラウザはアニメを再生するほかにも、発生しているイベントに応えたり、スクリプトのコンパイルに忙しかったりします。

  測ってみたところ、我々のブラウザの場合、1コマは5ミリ秒で処理できました。ただし、50ミリ秒ごとにガベージ・コレクションを行うブラウザでなければ、こうはならなかったと思われます。

  つまり、ブラウザはとんでもない数のコマを処理できるわけではないんですね。だからといって、滑らかなアニメーションを作れないと考えるのは早計です。
 

  先ほども書いた通り、無駄な計算を省いたアニメーションを作ることは可能です。ぎこちなさはレイヤーを駆使すれば解決できます。ブラウザは、分割した処理になら長けています。

  我々作り手側にできることは、その性質をうまく使ってアニメを作成することです。なおかつ、レイヤー機能はブラウザの一部なので、ウェブアプリに活用することもできます。
 

  このように、手軽に無駄なくアニメを作成できることから、ウェブ開発にElement.animate()を使用することを、ぜひ考えていただきたいのです。

  たとえば、このようなアニメを、たった次のコードで実現できます。

 elem.animate({ transform: [ 'rotate(0deg)', 'rotate(360deg)' ] },

         { duration: 1000, iterations: Infinity });

 

 

  記述の方法は、だいたい他のスクリプトと変わらないでしょう。それに、これならイベントハンドラもすぐさま実行できます。

  もちろん、これと同じようなものは、 CSS AnimationsCSS Transitionsでも十分に可能ですが、アプリケーションによってはスクリプトのほうが適している場合もあります。
  (ちなみに、CSS Animations と CSS Transitionsは、ウェブアニメ対応ブラウザに搭載されている、同一のエンジンで動作しています。)

 

 確認の方法

  以上のことから、引っ掛かりのないウェブアニメを作るには、ほんのいくつかの事項を満たせば十分だということが、お分かりいただけましたね。(transformopacityなどのプロパティ、レイヤーを作ること、アニメを再生する前には通知を入れることなど)

  では、これまでの作業を確認するには、どうすればよいのでしょう。

  Firefoxの開発者ツールには、アニメーション・インスペクターという機能があります。ここに設定されているプロパティが表示されます。現在処理中のプロパティには、小さな雷マークが表示されます。

  さらにこのツールには、あなたのアニメーションがきちんと読み取られなかった場合に、その理由を表示する機能がついています。(Firefox 49時点)

  [スクリーンショット]アニメーション・インスペクター

  このツールの使い方は、MDNのページに詳しく記載されています。


 

 注意:このツールに記載されるお知らせが全て正しいとは限りません。これまで報告されたバグの中には、「アニメーションに遅延が出ている」という通知が、実は「レイヤーが正しく働いていない」という通知の間違いだったという事例があります。
  このようなことは、JavaScriptでのプログラミングが長すぎるときにもよく確認されています。

  アニメーションを途切れなく再生するには、自分が行った作業を確かめてみることが大切です。  
 

  レイヤーがうまく使えない場合、Element.animate()の使い方に問題があるかもしれません。まだCSSを使って減らせる無駄な演算があるのではないか見てみたり、プログラムの方法が他の言語とごっちゃになっていないかなどを確認してください。

  ブラウザ側にも問題がないか確認してみてください。電池を持たせる設定の中に「アニメは再生しない」という項目があるのではないか。そもそも、問題が起きているブラウザの性能は、単なるでっち上げではないかという可能性も疑ってみてください。実は後者が原因であることが、けっこうよくあるんです。



 

 おわりに

  Firefox 48で実装されたElement.animate()は、FirefoxとChromeの両方で使えるようになりました。
  それから、Element.animate()に対応していないブラウザにrequestAnimationFrameを使う時には、 polyfillというプログラムが代替システムとして使えます。(その中でも、 web-animations.min.jsがよいでしょう。) Polymerのようなフレームワークなので、すぐに使いこなせるでしょう。

  Web Animations APIは数あれど、今回ご紹介したElement.animate()があなたの開発のお役に立てれば幸いです。(ぜひ、こちらのデモもご覧ください。)


 

  Brian Birtlesについて

  Mozilla日本東京支社にて、Firefoxのレイアウトとアニメーションを研究、さらにW3Cにて、ウェブ・アニメ―ション、CSSアニメーションの説明書を編集している。SVGをアニメに応用する研究にも長年携わっている。

  (原文)写真は山で撮影してるのに、大の海好き。サーフィンやスイミングを学ぶのが夢。

 https://birtles.wordpress.com/

 @brianskold

2017-06-09 23:38:49 / Hnoss
原文サイトを表示
[ 原文 ] https://hacks.mozilla.org/2016/08/animating-like-you-just-dont-care-with-element-animate/
Creative Commons License この作品は、クリエイティブ・コモンズ・ライセンスの下でライセンスされています。
クリエイティブ・コモンズ・ライセンス