Chromium 84 での Web Animations API の改善

Promise を使用したアニメーションのオーケストレーション、置き換え可能なアニメーションによるパフォーマンスの向上、複合モードによるスムーズなアニメーションなどの特長を備えています。

Kevin Ellis
Kevin Ellis

アニメーションを正しく使用すると、ユーザーの印象やブランドの記憶力が向上します。また、ユーザーにアクションを促し、アプリをナビゲートしやすくなるため、デジタル空間でコンテキストを得ることができます。

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 でアニメーションを作成する方法はよくわかるはずです。まず、キーフレーム オブジェクトを作成する必要があります。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;
}

次のように設定します。

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 でのデモを見る

そのためには、再生保留中のアニメーションを 2 つ(openModal とインラインの不透明度変換)作成し、一方のアニメーションを一時停止して、もう一方のアニメーションが終了するまで遅延させます。その後、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' 複合モードでは、最後のアニメーションが transform プロパティを置き換え、最終的に rotate(360deg) scale(1.4) になります。'add' の場合、複合は回転を追加してスケールを乗算し、最終状態は rotate(720deg) scale(1.96) になります。'accumulate' は変換を結合し、rotate(720deg) scale(1.8) になります。これらの複合モードの複雑さについて詳しくは、ウェブ アニメーション仕様の 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 の今後の展開

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