Chromium 84 での Web Animations API の改善

Promise によるアニメーションのオーケストレーション、置換可能なアニメーションによるパフォーマンスの向上、複合モードでのスムーズなアニメーションなど。

Kevin Ellis
Kevin Ellis

公開日: 2020 年 5 月 27 日

アニメーションは、正しく使用すると、ブランドの認知度や記憶が高まり、ユーザーのアクションを促して、ユーザーがアプリケーションを操作しやすくなり、デジタル空間にコンテキストがもたらされます。

Web Animations API は、デベロッパーが JavaScript で命令型アニメーションを作成するためのツールです。これは、CSS アニメーションと遷移の実装を支え、将来のエフェクトの開発や、既存のエフェクトの作成とタイミングの設定を可能にするために作成されました。

FirefoxSafari には仕様のすべての機能がすでに実装されていますが、Chromium 84 ではこれまでサポートされていなかった多くの機能が Chrome と Edge に導入され、ブラウザをまたいだ相互運用性を確保できるようになります。

Web Animations API は、2014 年 7 月のバージョン 36 で初めて Chromium に導入されました。2020 年 7 月にリリースされるバージョン 84 で、この仕様は完成する予定です。
Chromium の Web Animations API の長い歴史。

スタートガイド

@keyframe ルールを使用したことがある方は、Web Animations API を使用してアニメーションを作成できます。まず、Keyframe オブジェクトを作成する必要があります。CSS では次のように記述します。

@keyframes openAnimation {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

は JavaScript では次のようになります。

const openAnimation = [
  { transform: 'scale(0)' },
  { transform: 'scale(1)' },
];

CSS でアニメーションのパラメータを設定する場所は次のとおりです。

.modal {
  animation: openAnimation 1s 1 ease-in;
}

JS で次のように設定します。

document.querySelector('.modal').animate(
    openAnimation, {
      duration: 1000, // 1s
      iterations: 1, // single iteration
      easing: 'ease-in' // easing function
    }
);

コードの量はほぼ同じですが、JavaScript を使用すると、CSS だけでは得られない優れた機能がいくつかあります。これには、エフェクトのシーケンス設定や、再生状態のより細かい制御が含まれます。

element.animate()

ただし、今回の更新により、Web Animations API は element.animate() を使用して作成されたアニメーションに限定されなくなりました。CSS のアニメーションや遷移も操作できます。

getAnimations() は、要素が element.animate() で作成されたか、CSS ルール(CSS アニメーションまたは遷移)を使用して作成されたかにかかわらず、要素のすべてのアニメーションを返すメソッドです。次に例を示します。

まず、遷移のキーフレームを "get" して、遷移元を決定します。次に、新しい不透明度アニメーションを 2 つ作成して、クロスフェード効果を有効にします。クロスフェードが完了したら、コピーを削除します。

Promise を使用してアニメーションをオーケストレートする方法

Chromium 84 では、Promise で使用できるメソッドが animation.readyanimation.finished の 2 つになりました。

  • animation.ready を使用すると、保留中の変更が有効になるまで待機できます(再生と一時停止などの再生操作方法の切り替えなど)。
  • animation.finished は、アニメーションが完了したときにカスタム JavaScript コードを実行する手段を提供します。

例を続け、animation.finished を使用してオーケストレートされたアニメーション チェーンを作成します。ここでは、垂直変換(scaleY)の後に水平変換(scaleX)が続き、子要素の不透明度が変更されます。

開くモーダル要素に変換と不透明度を適用しています。Codepen でデモを確認する
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});

チェーン内の次のアニメーション セットを実行する前に、animation.finished.then() を使用してこれらのアニメーションを連結しています。アニメーションが順番どおりに表示され、さまざまなオプション(速度や簡単さなど)を設定してさまざまなターゲット要素に効果を適用できます。

CSS では、特に複数の要素にユニークでシーケンス化されたアニメーションを適用する場合、この再現は煩雑になります。@keyframe を使用して、アニメーションを配置する正しいタイミングの割合を整理し、シーケンス内のアニメーションをトリガーする前に animation-delay を使用する必要があります。

例: 再生、一時停止、巻き戻し

開くことができるものは、閉じることができるはずです。幸いなことに、Chromium 39 以降、Web Animations API によってアニメーションの再生、一時停止、反転の機能が提供されるようになりました。

前に表示したアニメーションを、.reverse() を使用してボタンをもう一度クリックしたときにスムーズに逆再生するアニメーションにできます。これにより、モーダルの操作がよりスムーズになり、コンテキストに沿ったものになります。

ボタンのクリックでモーダルが開閉する例。Glitch のデモを見る

再生が保留になるアニメーション(openModal とインライン不透明度変換)を 2 つ作成し、一方のアニメーションを一時停止して、もう一方のアニメーションが終了するまで遅らせることができます。Promise を使用すると、各 Promise が終了するのを待ってからプレイできます。最後に、フラグが設定されているかどうかを確認し、各アニメーションを逆再生します。

例: 部分的なキーフレームを使用した動的インタラクション

リターゲティングの例。マウスクリックでアニメーションを新しい位置に調整します。Glitch でデモを見る
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

この例では、キーフレームは 1 つしかなく、開始位置は指定されていません。これは、部分的なキーフレームを使用する例です。マウスハンドラはここでいくつかの処理を行います。つまり、新しい終了位置を設定し、新しいアニメーションをトリガーします。新しい開始位置は、現在の元の位置から推定されます。

既存の切り替えが実行されている間に、新しい切り替えをトリガーできます。つまり、現在の移行が中断され、新しい遷移が作成されます。

交換可能なアニメーションによるパフォーマンスの向上

'mousemove' などのイベントに基づいてアニメーションを作成すると、毎回新しいアニメーションが作成されるため、メモリが急速に消費され、パフォーマンスが低下する可能性があります。この問題に対処するため、Chromium 83 で交換可能なアニメーションが導入され、自動クリーンアップが可能になりました。終了したアニメーションは交換可能としてフラグが付けられ、別の終了したアニメーションに置き換えられた場合は自動的に削除されます。たとえば次のようになります。

マウスを動かすと彗星の尾がアニメーション化されます。Glitch でデモを見る
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

マウスを動かすたびに、ブラウザは彗星の尾の各ボールの位置を再計算し、この新しいポイントへのアニメーションを作成します。次の場合、ブラウザは古いアニメーションを削除(置き換えを有効化)するようになりました。

  1. アニメーションが完了します。
  2. コンポジションの順序で上位にある 1 つ以上のアニメーションも完了している。
  3. 新しいアニメーションでアニメーション化されるプロパティが同じである。

anim.onremove を使用してカウンタをトリガーし、削除されたアニメーションごとにカウンタを加算することで、置き換えられているアニメーションの数を正確に確認できます。

アニメーションの制御をさらに細かく行う方法がいくつかあります。

  • animation.replaceState() は、アニメーションがアクティブか、保持されているか、削除されたかをトラッキングする手段を提供します。
  • animation.commitStyles() は、基盤となるスタイルに基づいて要素のスタイルを更新し、要素のすべてのアニメーションを複合順序で更新します。
  • animation.persist() は、アニメーションを交換不可としてマークします。

合成モードによるスムーズなアニメーション

Web Animations API を使用すると、アニメーションの合成モードを設定できるようになりました。つまり、デフォルトのモードである「置換」に加えて、加算モードまたは累積モードを指定できます。合成モードを使用すると、デベロッパーは個別のアニメーションを作成して、効果の組み合わせを制御できます。'replace'(デフォルト モード)、'add''accumulate' の 3 つの複合モードがサポートされるようになりました。

アニメーションを合成する場合、デベロッパーは短く明確な効果を記述し、それらを組み合わせて表示できます。次の例では、各ボックスに回転とスケールのキーフレームを適用しています。調整は、オプションとして追加された合成モードのみです。

デフォルト、加算、累積の合成モードを示すデモ。Glitch のデモを見る

デフォルトの 'replace' コンポジット モードでは、最終的なアニメーションが変換プロパティに置き換えられ、rotate(360deg) scale(1.4) で終了します。'add' の場合、合成は回転を追加し、スケールを乗算して、最終状態 rotate(720deg) scale(1.96) になります。'accumulate' は変換を組み合わせて rotate(720deg) scale(1.8) を生成します。これらの複合モードの詳細については、Web アニメーションの仕様で CompositeOperation 列挙型と CompositeOperationOrAuto 列挙型をご覧ください。

次の UI 要素の例をご覧ください。

2 つの合成アニメーションが適用された弾むプルダウン メニュー。Glitch でデモを見る

ここでは、2 つの top アニメーションが合成されています。1 つ目はマクロ アニメーションで、ページの上部からスライドイン エフェクトとしてプルダウンをメニュー自体の全高分移動させます。2 つ目はマイクロ アニメーションで、下部に達すると少しバウンドします。'add' 複合モードを使用すると、遷移がより滑らかになります。

const dropDown = menu.animate(
    [
      { top: `${-menuHeight}px`, easing: 'ease-in' },
      { top: 0 }
    ], { duration: 300, fill: 'forwards' });

  dropDown.finished.then(() => {
    const bounce = menu.animate(
      [
        { top: '0px', easing: 'ease-in' },
        { top: '10px', easing: 'ease-out' },
        { ... }
      ], { duration: 300, composite: 'add' });
  });

Web Animations API の今後の予定

これらは、現在のブラウザのアニメーション機能に追加された新機能です。今後もさらに追加される予定です。今後の予定について詳しくは、以下の仕様をご覧ください。