TokyoFacebookTwitterHatenaPocketWebサイトを楽しく見せることができるフレームアニメーション。SVG画像とCSS、JavaScriptで滑らかな動きを実現する方法、注意点を解説します。デザイナーから、「今回のプロジェクトではフレームアニメーションを使いたいんだ。フロントエンド開発者には、デスクトップとモバイルを問わず、すべてのブラウザーで滑らかに動き、ハイパフォーマンスでメンテナンスしやすいフレームアニメーションの実装が求められます。このチュートリアルでは、HTML、CSS、JavaScriptを使ってアニメーションを作成する方法を紹介します。改善を繰り返しながら、プロジェクトにとって最善の結果を達成しましょう。フレームアニメーションとは?フレームアニメーションについてのAdobeによる定義は以下のとおりです。すべてのフレームでステージのコンテンツが変化するので、単にステージ上を移動するようなアニメーションではなく、画像が各フレームで変化するような複雑なアニメーションに適しています。言い換えると、アニメーションの対象は一連の画像によって表現されます。各画像がアニメーションの1フレームを形成し、フレームが次のフレームに置き変わる変化のレートによって、画像が動いているような錯覚を生み出します。ZeissのWebサイトのアニメーション「まばたきする目」を作成しながら、ワークフロー全体を説明します。アニメーションフレームの作成に使う一連の画像と、完成イメージです。このチュートリアルでは、レスポンシブWebデザインに対応し、いろいろなサイズの画面に合わせてスケーリングするメリットからSVG画像を使います。SVG画像を使いたくないなら、PNG、JPEG、GIF画像フォーマットやHTML5のCanvasを使ってWebアニメーションを制作できます。代替手段は記事の最後で紹介します。分かりやすくするため、jQueryライブラリーとAutoprefixerを使います。コードにブラウザー固有のCSSプレフィックスは付けません。コーディングを始めます。1.ソース画像の切替によるフレームアニメーション最初の方法はとても簡単です。HTMLドキュメントにimg要素を作成します。この要素は複数の画像のコンテナとして機能し、一度に1つずつ、アニメーションフレームを次のフレームに置きかえます。animation"/>CSSは以下のとおりです。300px;}次のステップは、一定の間隔で現在の画像を次の画像に動的に置きかえます。これで動いているような錯覚を生み出します。setTimeoutでも実装できますが、requestAnimationFrameならパフォーマンスの観点から以下のメリットが得られます。requestAnimationFrame(step);}ページロード時にrequestAnimationFrameを呼び出し、この関数に組み込まれたアニメーションのstartTimeパラメーターと、step関数を渡します。コードの各ステップで、ソース画像が更新されてからの経過時間をチェックします。経過時間がフレームの所要時間を超過すると画像を更新します。ここでは無限に繰り返すアニメーションを作成します。上のコードでは最後のフレームかチェックし、最後ならframeNumberを1にリセットします。それ以外はframeNumberを「1」インクリメントします。コードで簡単に画像をループできるように、画像の名前は「images/Eye-1.svg」「images/Eye-2.svg」「images/Eye-3.svg」のように増加する連番を持つ同一構造にし、同じ場所に置きます。最後に再びrequestAnimationFrameを呼び出し、プロセス全体を続行します。このままでは、アニメーションの開始時、最初の画像しかロードされないため動きません。アニメーションのループ中にimg要素のsrc属性をコードが更新するまで、表示するほかの画像がブラウザーに伝わらないため起こります。アニメーションをスムーズに動かすには、ループ開始前に画像をプリロードします。実現する方法はいろいろあります。気に入っているのは、以下に示すように複数のdivを非表示(hidden)にして追加し、background-imageプロパティの設定で目的の画像を示す方法です。}});完成したCodePenのデモです。この手法のメリットとデメリットを挙げます。v1.1では、複数の画像のロードが必要な場合、初回アクセス時にページのロード時間が長くなることがあるモバイル機器でアニメーションの品質が低下する場合がある。Lewisのブログ投稿を参照)メリット:宣言的:コードは一連の画像をループするだけでよい画像が1カ所に固定される:画像の表示がブレない(メリットになる理由は後述)2.画像の透明度変更によるフレームアニメーションブラウザーによる再描画を避けるため、ソース画像を置きかえる代わりに画像の透明度(opacity)を変更します。これでレンダリングパフォーマンスは改善されますが、画像をすべてプリロードすることは変わりません(ページにほかの画像が複数あり、すべてロードされるまで待つのが望ましくない場合、面倒なことになりかねません)。画像が複数あるため、初回のページロード時間が長くなります。コード全体を以下に示します。Pug、Twig、React、Angularといったテンプレートエンジン機能や、例のようにJavaScriptを使って複数のdivを追加すればHTMLコードの重複を避けられます。3.スプライトの位置変更によるフレームアニメーション複数の画像のダウンロードを回避するには、1枚のスプライト画像を使います。ここまでバラバラに作っていたフレーム画像を順番に1列に並べ、1枚にまとめたスプライト画像を作ります。最初の画像を左、最後の画像を右にして、CSSアニメーションでフレームごとにスプライトを左から右に動かすわけです。}}上のコードではフレーム数に合わせてbackground-sizeプロパティを設定しています。フレーム数が18なので、設定は1800%です。開始時のbackground-position値をleftに設定し、アニメーション開始時に最初の画像を表示します。コードではキーフレームアニメーションを使ってanimation-durationプロパティに設定した時間(上の例では1.3s)をかけて背景の位置を徐々にright(右)に変化させています。animation-timing-functionプロパティでstepごとのアニメーションを作成すれば、隣り合うフレームを同時に半分ずつ表示するのを確実に避けられます。animation(CSSスプライトシートアニメーションの紹介)に解説があります。JavaScriptは不要です。画像を1つだけロードするので、初回ページロード時のパフォーマンスが良好4.Transformでスプライトを動かすことによるフレームアニメーション前述の方法と同様、ブラウザーの再描画を避けることで、これまでに実装したソリューションをアップグレードします。background-positionプロパティではなくtransformプロパティを変更することで実現します。ラッパー内にアニメーションさせるdivを置きます。背景ではなくHTML要素全体の位置を置き換えます。次に、divをラッパー内でposition:absoluteに設定し、translateXプロパティを使ってアニメーションを開始します。100%」の計算結果です)。}}明らかに良くなりました。IEは、translateプロパティで値の%指定が使えないバグがあります。IEではtranslateプロパティで値を%指定できません。issues(既知の問題)タブに例と説明が掲載されています。transform」の値をアニメーションに使用するとピクセル値として解釈するバグがあります。フォールバックとして、JavaScriptを使ってブラウザーを検出し、特定のケース用に別のアニメーションを作成する必要があります。0)で、要素を別の構成レイヤーに移すようブラウザーに指示することで、レンダリングパフォーマンスが改善されます。}}下のライブデモでコードを試してください。可能な改善策に、外部リソースで画像を指定する代わりにSVG画像をインライン化する(つまりHTMLページに直接SVGコードを投入する)方法があります。一般的に、外部リソースはブラウザーがキャッシュします。再アクセス時に、ブラウザーはサーバーにリクエストを送らずにローカルにキャッシュしたファイルを使います。ランディングページなどの再アクセスの可能性が低いページには、インラインSVGが有意義です。サーバーへのリクエスト数を減らし、初回ページロード時間を短縮できます。レンダリングパフォーマンスにはスプライトのTransform(Sprite-Transform)パフォーマンスを正確に紹介するため、4つの手法すべてのパフォーマンスをテストしました。Chromeを使ったテスト結果です。試してみたい人は、任意のブラウザーを選んでjsPerf.comでテストを再現できます。5.WebのフレームアニメーションでGIFを使わない理由サイズの異なる画面に合わせたスケーリング機能が不要なら、GIFファイルも選択肢にできますが、スケーラビリティだけでなく、停止や逆再生、別のアニメーションとの結合といった制御機能は期待できません。ファイルサイズも大きくなり、パフォーマンスに影響します。Soueidanの記事を参考にしてください。小さい画面で一度に複数の要素を使ったアニメーションを作るなら、パフォーマンスが抜群なCanvasがおすすめですが、デメリットもあります。Canvasではインラインアセットが使えない。APIの知識が必要で、アプリケーションのメンテナンスコストが増加するDOMのイベントに対応していない。アニメーションが終わると、canvas要素外のDOMでは使えないCanvasとSVGを比較した賛否をめぐる議論はこちらです。Maloneのチュートリアルを参考にしてください。最善の結果を実現できる方法について説明があります。最後にWebのフレームアニメーション実装用に使う選択肢はたくさんあります。その中から最善のものを選ぶとなると迷います。選択時に役立つポイントを示します。Mainardiが査読を担当しています。最高のコンテンツに仕上げるために尽力してくれたSitePointの査読担当者のみなさんに感謝します。Romanovフロントエンドに熱心で、すべてのデザイナーの友です。詳しくはBuzzwooで。