ウェブ アニメーション - element.animate() を Chrome 36 で利用可能に

Brendan Kenny
Brendan Kenny

ウェブにおけるアニメーションは、かつて JavaScript が主流でしたが、世界がモバイルに移行するにつれ、アニメーションを宣言構文とブラウザで実現できる最適化を行うため CSS に移行しました。モバイルで 60 fps を常に目標にしているので、ブラウザが効率的に表示する方法から逸脱しないのは理にかなっています。

JavaScript を活用したアニメーションの効率を向上させるツールが増えてきていますが、最も重要なのは、宣言型アニメーションと命令型アニメーションの統合です。アニメーションの作成方法の決定は、最も明確なコードに基づいて決定され、一方のフォームでできることではなく、他方のフォームでできることではありません。

そのような要望に応えるのが Web Animations です。その第 1 部は、Chrome 36 で element.animate() の形式で提供されます。この新しい関数を使用すると、アニメーションを JavaScript だけで作成し、他の CSS アニメーションや遷移と同じように効率的に実行できます(実際、Chrome 34 では、これらすべてのメソッドでまったく同じウェブ アニメーション エンジンが使用されます)。

構文はシンプルで、CSS の遷移やアニメーションを記述したことがあるなら、その各部分はおなじみのものでしょう。

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

この新機能の最大の利点は、スムーズでジャンクのないアニメーションにするために、これまで必要だった多くの面倒な作業を省くことができることです。

たとえば、昨年の「サンタを追いかけよう」では、雪が降り続けたいため、効率的に処理できるよう CSS を使ってアニメーション化しました。

しかし、雪の水平方向の位置を、画面とシーン自体で発生しているイベントに基づいて動的に選択したいと考えました。雪の降る高さ(ユーザーのブラウザ ウィンドウの高さ)は、実際に走行するまでわかりません。つまり、CSS 遷移を使用する必要がありました。実行時に CSS アニメーションを作成すると、すぐに複雑になります(スノーフレークが数百個あると、何百もの新しいスタイル設定ルールが必要になります)。

そこで、おなじみのアプローチを採用しました。

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)';

重要なのは「フレームを待つ」という動作です。あります。遷移を正常に開始するには、要素が開始位置にあることをブラウザが確認する必要があります。これにはいくつかの方法があります。最も一般的な方法の 1 つは、ブラウザにレイアウトの計算を強制する要素プロパティの 1 つから読み込み、それによって、終了位置に移行する前に要素が開始位置にあることを確認することです。この方法により、ブラウザ内部構造に関する豊富な知識を身につけられるだけでなく、キーボード入力するたびに面倒な作業を行うこともできます。

これに対して、これに対応する element.animate() の呼び出しは、何の意図があったのかを正確に伝えて、これほど明確に表現することはできません。

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

他にも多くのオプションがあります。対応する CSS と同様に、ウェブ アニメーションも遅延や反復処理が可能です。

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

実際には、element.animate() は AnimationPlayer オブジェクトを返します。このオブジェクトは、Web Animations 仕様が増えるにつれてますます重要になります。JavaScript で作成されたアニメーションと CSS で作成されたアニメーションの両方に AnimationPlayer が関連付けられ、便利で興味深い方法でシームレスに組み合わせるようになります。

ただし、今のところ、AnimationPlayer の機能は 2 つしかなく、どちらも非常に便利です。AnimationPlayer.cancel() を使用すると、いつでもアニメーションをキャンセルできます。

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

また、過去に CSS アニメーションや遷移のアニメーション システムを構築しようとしていた方も安心です。ウェブ アニメーションが終了すると、常にイベントが発生します。

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

試してみる

この機能はすべて Chrome 36 でリリースされ、本日よりベータ版に移行されます。ぜひ、Chrome 36 のネイティブ実装をお試しください。一方、Web Animations ポリフィルを使用すると、Web Animations の全仕様のかなりの部分を、常に最新のブラウザで利用できます。

ネイティブ バージョンの element.animate()ポリフィルの両方を使用して、雪効果のデモを利用できます。

ご意見をお寄せください

ただし、これは今後リリースされる機能のプレビュー版であり、デベロッパーの皆様からのフィードバックを直ちに得るために、特別にリリースされるものです。すべてのユースケースに対応するのか、それともアニメーション用に現在の API を手早く済ませたのかは、まだわかりません。Google がこれを把握し、真に理解するための唯一の方法は、デベロッパーの皆様が実際にお試しいただき、ご意見を伺うことです。

もちろん、この投稿のコメントは貴重です。標準自体に関するコメントは、public-fx メーリング リストから CSS および SVG ワーキング グループ宛てに送信できます。

2014 年 10 月更新: Chrome 39 では、再生の制御に関連するいくつかのメソッドplay()pause()reverse() など)のサポートが追加されています。また、currentTime プロパティを使用して、アニメーションのタイムライン内の特定のポイントにジャンプすることもできます。この機能の実際の動作は、こちらの新しいデモで確認できます。

この投稿に協力してくれた Addy Osmani と Max Heinritz に感謝します。