WebアニメーションAPIを使用した複雑さの調整

公開: 2022-03-10
簡単な要約↬WebAnimationsAPIにはオプションが多すぎて、簡単に選択できません。 タイミングがどのように機能するか、および複数のアニメーションの再生を一度に制御する方法を学ぶことは、プロジェクトの基礎となる強固な基盤になります。

単純なトランジションと複雑なアニメーションの間に中間点はありません。 CSSトランジションとアニメーションが提供するものに問題がないか、突然、取得できるすべてのパワーが必要になります。 Web Animations APIは、アニメーションを操作するための多くのツールを提供します。 しかし、あなたはそれらをどのように扱うかを知る必要があります。 この記事では、柔軟性を保ちながら複雑なアニメーションを処理するのに役立つ可能性のある主なポイントとテクニックについて説明します。

この記事に飛び込む前に、WebアニメーションAPIとJavaScriptの基本に精通していることが重要です。 明確にし、目前の問題から気を散らさないようにするために、提供されているコード例はわかりやすいものです。 関数やオブジェクトほど複雑なものはありません。 アニメーション自体への優れたエントリポイントとして、一般的なリファレンスとしてMDN、Daniel C. Wilsonの優れたシリーズ、OllieWilliamsによるCSSアニメーションとWebアニメーションAPIをお勧めします。 効果を定義し、希望する結果を達成するためにそれらを調整する方法については説明しません。 この記事では、アニメーションが定義されていて、それらを処理するためのアイデアとテクニックが必要であることを前提としています。

まず、インターフェースの概要とその目的から始めます。 次に、制御のタイミングとレベルを調べて、何を、いつ、どのくらいの期間で定義します。 その後、複数のアニメーションをオブジェクトでラップして1つとして扱う方法を学習します。 これは、WebAnimationsAPIを使用するための良いスタートになります。

インターフェース

Web Animations APIは、制御の新しい次元を提供します。 それ以前は、CSSトランジションとアニメーションは、効果を定義する強力な方法を提供しながら、単一の作動点を持っていました。 照明スイッチのように、それはオンかオフのどちらかでした。 ディレイやイージング機能を試して、非常に複雑なエフェクトを作成することができます。 それでも、ある時点で、それは面倒で扱いにくくなります。

Web Animations APIは、この単一の作動点を再生の完全な制御に変えます。 照明スイッチは、スライダー付きの調光スイッチに変わります。 再生コントロールに加えて、実行時にエフェクトを定義および変更できるようになったため、必要に応じて、スマートホーム全体に変えることができます。 これで、エフェクトをコンテキストに適合させることができます。または、リアルタイムプレビューを備えたアニメーションエディタを実装することもできます。

アニメーションインターフェースから始めます。 アニメーションオブジェクトを取得するには、 Element.animateメソッドを使用できます。 キーフレームとオプションを指定すると、アニメーションがすぐに再生されます。 また、 Animationオブジェクトインスタンスを返します。 その目的は、再生を制御することです。

これらを覚えているなら、それをカセットプレーヤーと考えてください。 一部の読者はそれが何であるかをよく知らないかもしれないことを私は知っています。 現実世界の概念を適用して抽象的なコンピューターのことを説明しようとすると、すぐに崩壊することは避けられません。 しかし、鉛筆でテープを巻き戻すことの喜びを知らない読者であるあなたに、カセットプレーヤーが何であるかを知っている人々がこの記事の終わりまでにさらに混乱することを安心させてください。

ボックスを想像してみてください。 カセットを入れるスロットがあり、再生、停止、巻き戻しのボタンがあります。 これが、アニメーションインターフェイスインスタンスです。定義されたアニメーションを保持し、その再生を操作する方法を提供するボックスです。 あなたはそれに何かをプレイするために与え、それはあなたにコントロールを戻します。

取得するコントロールは、オーディオおよびビデオ要素から取得するコントロールと便利に似ています。 これらは、再生メソッドと一時停止メソッド、および現在の時刻プロパティです。 これらの3つのコントロールを使用すると、再生に関しては何でも作成できます。

カセット自体は、アニメーション化される要素への参照、エフェクトの定義、および特にタイミングを含むオプションを含むパッケージです。 そしてそれがKeyframeEffectです。 私たちのカセットテープは、すべての録音と録音の長さに関する情報を保持するものです。 これらすべてのプロパティを物理的なカセットのコンポーネントと一致させるために、年配の聴衆の想像力に任せます。 私がお見せするのは、コードでどのように見えるかです。

Element.animateを使用してアニメーションを作成するときは、3つのことを行うショートカットを使用しています。 KeyframeEffectインスタンスを作成します。 新しいAnimationインスタンスに入れます。 すぐに再生を開始します。

 const animation = element.animate(keyframes, options);

それを分解して、同じことをする同等のコードを見てみましょう。

 const animation = new Animation( // (2) new KeyframeEffect(element, keyframes, options) // (1) ); animation.play(); (3)

カセット(1)を入手し、プレーヤー(2)に入れてから、再生ボタン(3)を押します。

それが舞台裏でどのように機能するかを知ることのポイントは、キーフレームの定義を分離し、それをいつ再生するかを決定できるようにすることです。 調整するアニメーションがたくさんある場合は、最初にすべてを集めて、再生の準備ができていることを確認すると役立つ場合があります。 それらをその場で生成し、適切なタイミングで再生を開始することを期待することは、あなたが望んでいることではありません。 数フレームのドラッグで目的の効果を壊すのは簡単すぎます。 ドラッグが蓄積する長いシーケンスの場合、説得力のある経験はまったくありません。

ジャンプした後もっと! 以下を読み続けてください↓

タイミング

コメディのように、タイミングはアニメーションのすべてです。 エフェクトを機能させるには、特定の感触を実現するために、プロパティの変更方法を微調整できる必要があります。 WebAnimationsAPIで制御できるタイミングには2つのレベルがあります。

個々のプロパティのレベルでは、 offsetがあります。 オフセットを使用すると、単一のプロパティのタイミングを制御できます。 ゼロから1までの値を指定することにより、各エフェクトがいつ開始するかを定義します。省略した場合、ゼロになります。

CSSの@keyframesから、 from / toの代わりにパーセンテージを使用する方法を覚えているかもしれません。 それがoffsetですが、100で割ったものです。 offsetの値は、1回の反復の期間の一部です

offsetを使用すると、 KeyframeEffect内にキーフレームを配置できます。 相対的な数値オフセットであるため、再生の継続時間や速度に関係なく、すべてのキーフレームが相互に同時に開始するようになります。

前に述べたように、 offset期間の一部です。 今、私はあなたにこれに関する私の間違いと時間の損失を避けて欲しいです。 アニメーションの長さは、アニメーションの全体的な長さと同じではないことを理解することが重要です。 通常、それらは同じであり、それがあなたを混乱させる可能性があり、間違いなく私を混乱させたものです。

期間は、1回の反復が完了するまでにかかるミリ秒単位の時間です。 デフォルトでは、全体の継続時間と同じになります。 遅延を追加するか、アニメーション期間の反復回数を増やすと、知りたい回数が表示されなくなります。 それをあなたの利益のために使うことを理解することは重要です。

メディア再生など、より大きなコンテキスト内でキーフレーム再生を調整する必要がある場合は、タイミングオプションを使用する必要があります。 次の式で、開始から「終了」イベントまでのアニメーションの全期間。

 delay + (iterations × duration) + end delay

次のデモで実際の動作を確認できます。

Kirill Myshkinによるペン[アニメーションの実際の長さはどれくらいですか?](https://codepen.io/smashingmag/pen/VwWWrzz)を参照してください。

ペンを見るアニメーションの実際の長さはどれくらいですか? キリル・ミシュキン著。

これにより、固定長メディアのコンテキスト内でいくつかのアニメーションを整列させることができます。 アニメーションの目的の継続時間をそのまま維持して、開始時にdelayを、終了時にdelayEndを「埋める」ことで、より長い継続時間のコンテキストにアニメーションを埋め込むことができます。 あなたがそれについて考えるならば、この意味でのdelayは、オフセットがキーフレームで行うように機能します。 遅延はミリ秒単位で設定されるため、相対値に変換することをお勧めします。

アニメーションの調整に役立つもう1つのタイミングオプションは、 iterationStartです。 反復の開始位置を設定します。 ビリヤードボールのデモをご覧ください。 iterationStart開始スライダーを調整することで、ボールの開始位置と回転を設定できます。たとえば、画面の中央からジャンプを開始し、最後のフレームでカメラの数値をまっすぐにするように設定できます。

KirillMyshkinによるペン[TweakinterationStart](https://codepen.io/smashingmag/pen/qBjjVPR)を参照してください。

KirillMyshkinによるPenTweakinterationStartを参照してください。

複数を1つに制御する

プレゼンテーションアプリのアニメーションエディターで作業したとき、タイムライン上の1つの要素に対して複数のアニメーションを配置する必要がありました。 私の最初の試みは、 offsetを使用して、アニメーションをタイムラインの正しい開始点に配置することでした。

これは、 offsetを使用する間違った方法であることがすぐにわかりました。 タイムライン上のこの特定のUI移動アニメーションに関しては、アニメーションの継続時間を変更せずに開始位置をシフトすることを意味しました。 offsetを使用すると、いくつかの変更が必要になります。 offset自体と、クロージングプロパティのoffsetを変更して、期間が変更されないようにします。 解決策は複雑すぎて理解できないことが判明しました。

2番目の問題は、 transformプロパティにありました。 要素に対するいくつかの特徴的な変更を表すことができるという事実のために、それをあなたが望むことをさせるのは難しいかもしれません。 これらのプロパティを互いに独立して変更したい場合は、さらに困難になる可能性があります。 スケール機能の変更は、それに続くすべての機能に影響します。 これが起こる理由です。

Transformプロパティは、値としてシーケンス内のいくつかの関数を受け取ることができます。 関数の順序に応じて、結果が変わります。 scaleを取り、 translateします。 translateをパーセンテージで定義すると便利な場合があります。これは、要素のサイズに相対的な意味です。 ボールを正確に3つの直径の高さにジャンプさせたいとします。 ここで、スケール関数を配置する場所( translateの前または後)に応じて、結果は元のサイズまたはスケーリングされたサイズの3つの高さから変化します。

これは、 transformプロパティの重要な特性です。 非常に複雑な変換を実現するには、これが必要です。 ただし、これらの変換を区別して、要素の他の変換から独立させる必要がある場合は、邪魔になります。

すべての効果を1つのtransformプロパティに入れることができない場合があります。 かなり早く取得しすぎる可能性があります。 特に、キーフレームがさまざまな場所からのものである場合は、変換された文字列を非常に複雑にマージする必要があります。 ロジックが単純ではないため、自動メカニズムに頼ることはほとんどできません。 また、何を期待するのか理解するのが難しくなる可能性があります。 これを単純化し、柔軟性を維持するには、それらを異なるチャネルに分離する必要があります。

1つの解決策は、要素をdivにラップして、それぞれを個別にアニメーション化できるようにすることです。たとえば、キャンバス上に配置するためのdiv、スケーリング用のdiv、回転用のdivなどです。 そうすることで、アニメーションの定義を大幅に簡素化するだけでなく、必要に応じてさまざまな変換原点を定義する可能性も広がります。

そのトリックで物事が制御不能になるように見えるかもしれません。 以前に抱えていた問題の数を増やしていること。 実際、このトリックを最初に見つけたとき、私はそれを多すぎるとして破棄しました。 私は、自分のtransformプロパティがすべてのピースから正しい順序で1つのピースにコンパイルされていることを確認できると思いました。 物事を管理するには複雑すぎ、特定のことは不可能にするために、もう1つのtransform関数が必要でした。 私のtransformプロパティ文字列コンパイラは、正しく動作するのにますます時間がかかり始めたので、あきらめました。

いくつかのアニメーションの再生を制御することは、当初のように難しいことではないことが判明しました。 カセットテーププレーヤーの例えを最初から覚えていますか? 任意の数のカセットを使用する独自のプレーヤーを使用できるとしたらどうでしょうか。 それ以上に、そのプレーヤーに必要な数のボタンを追加できます。

単一のアニメーションと一連のアニメーションでplayを呼び出すことの唯一の違いは、反復する必要があることです。 Animationインスタンスの任意のメソッドに使用できるコードは次のとおりです。

 // To play just call play on all of them animations.forEach((animation) => animation.play());

これを使用して、プレーヤーのあらゆる種類の関数を作成します。

アニメーションを保持して再生するボックスを作成しましょう。 これらのボックスは、適切な方法で作成できます。 明確にするために、関数とオブジェクトを使用してそれを行う例を示します。 createPlayer関数は、同期して再生されるアニメーションの配列を取ります。 単一のplayメソッドを持つオブジェクトを返します。

 function createPlayer(animations) { return Object.freeze({ play: function () { animations.forEach((animation) => animation.play()); } }); }

機能の拡張を開始するために知っておくには、これで十分です。 pauseメソッドとcurrentTimeメソッドを追加しましょう。

 function createPlayer(animations) { return Object.freeze({ play: function () { animations.forEach((animation) => animation.play()); }, pause: function () { animations.forEach((animation) => animation.pause()); }, currentTime: function (time = 0) { animations.forEach((animation) => animation.currentTime = time); } }); }

これらの3つのメソッドを使用したcreatePlayerを使用すると、任意の数のアニメーションをオーケストレーションするのに十分な制御が可能になります。 しかし、もう少し推し進めましょう。 私たちのプレーヤーがカセットをいくつでも取ることができるだけでなく、他のプレーヤーも取ることができるようにしましょう。

前に見たように、 Animationインターフェイスはメディアインターフェイスに似ています。 その類似性を使用して、プレーヤーにあらゆる種類のものを入れることができます。 これに対応するために、 currentTimeメソッドを微調整して、アニメーションオブジェクトとcreatePlayerからのオブジェクトの両方で機能するようにします。

 function currentTime(time = 0) { animations.forEach(function (animation) { if (typeof animation.currentTime === "function") { animation.currentTime(time); } else { animation.currentTime = time; } }); }

作成したばかりのプレーヤーは、単一要素のアニメーションチャネルのいくつかのdiv複雑さを隠すことができるものです。 これらの要素は、シーンにグループ化できます。 そして、各シーンは何か大きなものの一部になる可能性があります。 このテクニックでできることはすべて。

タイミングのデモを示すために、すべてのアニメーションを3人のプレーヤーに分割しました。 1つ目は、右側のプレビューの再生を制御することです。 2つ目は、左側にあるすべてのボールのアウトラインとプレビュー中のボールのジャンプアニメーションを組み合わせたものです。

最後に、3つ目は、左側のコンテナ内のボールの位置アニメーションを組み合わせたプレーヤーです。 そのプレーヤーは、毎秒約60フレームのスライスを使用して、アニメーションの継続的なデモンストレーションでボールを広げることができます。

結論

Web Animations APIのようなWebインターフェースは、ブラウザーがずっと行ってきた特定のことを私たちに公開します。 ブラウザは、GPUに作業を渡すことで高速にレンダリングする方法を知っています。 Web Animations APIを使用すると、それを制御できます。 そのコントロールは少し異質または混乱しているように見えるかもしれませんが、それを使用することも混乱するはずだという意味ではありません。 タイミングと再生制御を理解すると、そのAPIをニーズに合わせて調整するためのツールが得られます。 あなたはそれがどれほど複雑であるべきかを定義することができるはずです。

参考文献

  • 「アニメーションのデザインに関する実践的なテクニック」、サラ・ドラスナー
  • 「モーション感度のためにモーションを減らして設計する」、Val Head
  • 「音声アシスタントの代替音声UI」、Ottomatias Peura
  • 「モバイルユーザーインターフェイス用のより優れたツールチップの設計」、Eric Olive