前回の記事「JSX を使用したカルーセル コンポーネントの実装」では、「基本的な」カルーセル コンポーネントを実装しました。なぜ「財団」と呼ぶのでしょうか?弊社のカルーセル コンポーネントの機能を満たすことはできているようですが、まだ完成していない欠陥が多数あります。 これには 2 つの機能が実装されていますが、1 つは自動カルーセル、もう 1 つはジェスチャ ドラッグです。しかし、実際には、まだ実際に使える状態には程遠いのです。 まず、自動カルーセルとドラッグはシームレスに接続できません。つまり、ドラッグを終了した後、カルーセルは自動的に回転し続ける必要があります。私たちはまだこれを達成していません。ドラッグ自体にも細かい問題があります。たとえば、現在はマウスのドラッグ イベントのみがサポートされており、タッチ スクリーンのドラッグはサポートされていません。これも、Web ページの開発中に直面しなければならない問題です。 次に、アニメーションは それでは、アニメーション ライブラリを一緒に実装してみましょう。ただし、アニメーション ライブラリを実装する前に、アニメーション ライブラリにタイムライン ライブラリが必要です。この記事では、まずタイムライン クラスと、このタイムラインを使用するための基本的なアニメーション クラスを実装する方法について説明します。 コードのクリーニングまず、前に書いた Carousel コンポーネントのコードがすでに非常に複雑であることがわかったので、それをカプセル化する必要があります。ここでは、それを別の JavaScript ファイルに配置します。 プロジェクトのルート ディレクトリに carousel.js では、 './framework.js' から { コンポーネント } をインポートします。 export class Carousel extends Component ** Carousel 内のコード */ 最後に、main.js に Carousel コンポーネントを再インポートできます。 './framework.js' から Component、createElement をインポートします。 './carousel.js' から { Carousel } をインポートします。 ギャラリー = [ 'https://source.unsplash.com/Y8lCoTRgHPE/1600x900', 'https://source.unsplash.com/v7daTKlZzaw/1600x900', 'https://source.unsplash.com/DlkF4-dbCOU/1600x900', 'https://source.unsplash.com/8SQ6xjkxkCo/1600x900', ]; a = <Carousel src={gallery} /> とします。 // document.body.appendChild(a); ドキュメントの本文にマウントします。 コードを整理したら、タイムライン ライブラリの作成を開始できます。このタイムラインはアニメーション ライブラリの一部なので、アニメーション ライブラリの JavaScript ファイル ( このタイムラインを使用して後続のアニメーションライブラリを実装する必要がありますが、アニメーションには非常に重要な概念である「フレーム」があります。
JavaScript の「フレーム」アニメーションを実現するには「フレーム」が必要なので、まず JavaScript でのいくつかのフレーム処理ソリューションを理解する必要があります。 人間の目が認識できるアニメーションの最高周波数は60 フレームです。 学生の中にはアン・リー監督の映画を見たことがある人もいるかもしれません。たとえば、「ビリー・リンのロング・ハーフタイム・ウォーク」は、120 フレームで撮影され再生された世界初の映画です。 また、フレームレートが2倍になったため、多くの場所が非常にスムーズに感じられるでしょう。しかし、一般的に言えば、モニターを含む当社のゲームはすべて 60 フレームをサポートしています。モニターの設定では 70 または 80 フレームが表示されることがありますが、一般的なソフトウェアでは 60 フレームに揃えられます。 1000 ミリ秒 (1 秒) に 60 フレームが必要な場合、1 フレームは何ミリ秒になりますか?つまり、1000 / 60 = 16.666 1000 / 60 = 16.666 1000/60=16.666 なので、16 ミリ秒が 1 フレームの時間におおよそ相当します。
「フレーム」の実装方法次に、JavaScript で「フレーム」を実装するために使用できるメソッドを分析しましょう。 1. 間隔を設定する1 つ目は、カルーセルを作成するときに実際に使用した setInterval(() =>{/** 1 フレームで何が起こるか*/, 16) ここで設定される時間間隔は 1 フレームの長さである 16 ミリ秒です。 2.タイムアウトを設定するsetTimeout を使用して、1 つのフレーム内でイベントを繰り返し処理することもできます。しかし、setTimeout は一度しか実行されないためです。したがって、後で繰り返し呼び出せるように関数名を付ける必要があるのです。
これを使用する方法は、ティック関数を定義し、ロジック/イベントを実行させることです。次に、setTimeout を使用して、再度実行する前に 16 ミリ秒の遅延を追加します。 ティック = () => { /** ロジック/イベント*/ setTimout(ティック、16); } 3. アニメーションフレームをリクエストする最後に、最新のブラウザは ブラウザに次のフレームの実行を要求すると、RAF に渡されたコールバック関数が実行されます。この関数の実行時間はブラウザのフレームレートに関係します。 したがって、ブラウザのフレーム レートの削減や周波数の削減操作を実行する場合は、ブラウジングのフレーム レートとともに RAF を削減できます。 使い方も非常に簡単です: ティック = () => { /** ロジック/イベント*/ setTimout(ティック、16); } したがって、一般的にはこれら 3 つのソリューションが最もよく使用されます。ほとんどのユーザーが最新のブラウザを使用している場合は、 「なぜ setInterval を使わないのですか?」 setInterval は比較的制御しにくいため、ブラウザは設定した 16 ミリ秒に従ってそれを実行するでしょうか?それは言いにくいですね。 もう 1 つは、ティックが適切に記述されていない場合、setInterval がバックログされる可能性があることです。固定の 16 ミリ秒ループで実行されるため、前の間隔のコードが実行されたかどうかに関係なく、2 番目の間隔のコードは間隔キューに入ります。これもブラウザの基盤となる実装によって異なります。ブラウザごとに異なる戦略が選択される場合があります。
次のタイムライン ライブラリでは、requestAnimationFrame を使用して自己繰り返し操作を実行します。 ここでは、requestAnimationFrame に対応する cancelAnimationFrame についても言及する必要があります。 requestAnimationFrame を格納する変数を宣言すると、この変数を cancelAnimationFrame に渡してアニメーションを停止できます。 ティック = () => { ハンドラーを requestAnimationFrame(tick); に設定します。 アニメーションフレームをキャンセルします(ハンドラ); } こうすることで、リソースの無駄をある程度回避できます。 タイムラインの実装冒頭で述べたように、アニメーションを作成するときは、 次に、この Timeline クラスを一緒に実装してみましょう。通常、タイムラインは ただし、一時 もう 1 つは このアニメーションライブラリを設計する際には、 これはより高度なタイムライン関数であるため、このチュートリアルで実装されている設定レートと取得レートは実装されません。これを実現したいのであれば、関連する知識をたくさん学ぶ必要があります。しかし、 ここまでお話ししましたが、始めましょう! 〜 開始関数の実装開始メソッドでは、 では、ダニを完璧に隠すにはどうすればいいのでしょうか? animation.js ファイルのグローバル スコープで 同様に、tick 内の requestAnimationFrame も、それを保存するためのグローバル変数
これら 2 つの定数を使用して、Timeline クラスのコンストラクターでティックを初期化できます。 Tick を初期化した後、 最終的なコードは次のようになります。 const TICK = シンボル('tick'); const TICK_HANDLER = Symbol('tick-handler'); エクスポートクラスタイムライン{ コンストラクタ() { this[TICK] = () => { console.log('ティック'); アニメーションフレームをリクエストします(this[TICK]); }; } 始める() { this[TICK](); } 一時停止() {} 再開する() {} リセット() {} } この部分を完了したら、この Timeline クラスを main.js に導入して試すことができます。 './animation.js' から { Timeline } をインポートします。 tl = new Timeline(); tl.start(); コードをビルドしてブラウザで実行します。コンソールでティックが正常に実行されていることを確認できます。これは、タイムラインの現在のロジックが正しく記述されていることを示しています。 これまで、非常に基本的なタイムライン操作を実装しました。次に、タイムラインをテストするための簡単な Animation クラスを実装しましょう。 アニメーションクラスの実装次に、Tick にアニメーションを追加して実行します。 作成したタイムラインは、最終的にカルーセルのアニメーションで使用されます。カルーセル上のアニメーションは「属性アニメーション」と呼ばれます。 オブジェクトのプロパティをある値から別の値に変更しているためです。 属性アニメーションとは対照的に、フレームアニメーションは、1 秒ごとに 1 つの画像が表示されることを意味します。コマアニメーションといえば、宮崎駿監督の名作『となりのトトロ』や『天空の城ラピュタ』などのアニメーションを誰もが知っているのではないでしょうか。これらのアニメーションはすべて宮崎駿氏によって1枚ずつ描かれ、1フレームごとに1枚の絵が再生されます。高速再生プロセスでは、画像内の人物や物体が動いているのを見ることができます。アニメの時代よりもさらに以前にもアニメーションは存在しており、それを古代人はゾートロープと呼んでいました。 上記のアニメーションは属性を通じて実行されるものではありません。しかし、ブラウザで行うことのほとんどは属性アニメーションです。各アニメーションには、初期プロパティ値と終了プロパティ値があります。 アニメーションの理論を理解した後、この部分のロジックの実装を開始できます。まず、アニメーションのロジックはタイムラインから比較的独立しているため、アニメーションを別のクラスにカプセル化できます。 (フロントエンドのコンポーネント化に関する今後の記事では、アニメーション ライブラリの機能をさらに強化する予定です。 ) エクスポートクラス Animation { コンストラクタ() {} } まず、アニメーションを作成します。次のパラメータが必要です。
ここで注意する必要があるのは、渡されるプロパティには通常、 ただし、ここでは後で追加するのではなく、まずは簡単なアニメーションを実装しましょう。 Animation オブジェクトを初期化するときには、渡されたすべてのパラメータをこのオブジェクトのプロパティに保存する必要があるため、コンストラクターでは渡されたすべてのパラメータをそのままコピーする必要があります。 エクスポートクラス Animation { コンストラクター(オブジェクト、プロパティ、開始値、終了値、期間、タイミング関数) { this.object = オブジェクト; this.property = プロパティ; this.startValue = 開始値; this.endValue = endValue; this.duration = 期間; this.timingFunction = タイミング関数; } } 次に、アニメーションを実行する関数が必要です。 exec または go と呼ぶことができます。ここでは この関数は、仮想時間である この時間を使用して、この時間に基づいて現在のアニメーション プロパティがどれだけ変化するかを計算できます。このプロパティの変化を計算するには、まずアニメーションの初期値から最終値までの合計変化範囲を知る必要があります。
ここで取得した変更値は、現在の実行時間とアニメーションの合計期間に基づいて この変更値は、CSS アニメーションの この変更値を使用すると、startValue (初期値) + 変更値を使用して、現在の進行状況に対応する属性値を取得できます。コードの動作は次のようになります: 実行(時間) { 範囲を this.endValue - this.startValue とします。 this.object[this.property] = this.startValue + (範囲 * 時間) / this.duration; } この方法でアニメーションが機能します。次に、このアニメーションをタイムラインのアニメーション キューに追加して、キュー内で実行できるようにします。 上で述べたように、このアニメーションの run メソッドによって受信される時間は仮想時間です。したがって、Timeline で run メソッドを呼び出すときは、アニメーションが機能するように Animation に仮想時間を渡す必要があります。 さて、ここでタイムラインにアニメーションを追加したいのですが、まずアニメーション キューが必要です。このため、アニメーション セットを直接生成します。 これは他のタイムラインでの保存方法と同じです。保存するためにグローバル ANIMATIONS 定数を作成し、その値をシンボルにラップします。これにより、キューが誤って外部から呼び出されるのを防ぐことができます。 const ANIMATIONS = Symbol('animations'); Timeline クラスが構築されるときに、このキューに空のセットも割り当てられる必要があります。 コンストラクタ() { this[ANIMATIONS] = 新しい Set(); } キューがある場合は、キューに参加するメソッドが必要なので、Timeline クラスに コンストラクタ() { this[ANIMATIONS] = 新しい Set(); } タイムラインで ただし、以前の ただし、この変更により、タイムラインが開始されるたびにティック オブジェクト関数が再構築されることになります。ただし、この方法を使用すると、この機能をすばやく実装しやすくなりますが、より良いパフォーマンスを求める学生は、この領域を最適化することもできます。 ティックを移動した後、ANIMATIONS キューを呼び出すアニメーションをティックに追加できます。タイムラインには複数のアニメーションが存在する可能性があり、各フレームはそれらを次の進行状況属性状態にプッシュします。ここではループを使用して、ANIMATIONS キュー内のすべてのアニメーションの run メソッドを呼び出します。 最終的に、コードは次のようになります。 const TICK = シンボル('tick'); const TICK_HANDLER = Symbol('tick-handler'); const ANIMATIONS = Symbol('animations'); エクスポートクラスタイムライン{ コンストラクタ() { this[ANIMATIONS] = 新しい Set(); } 始める() { startTime を Date.now() とします。 this[TICK] = () => { t = Date.now() - startTime とします。 for (this[ANIMATIONS]のアニメーションをlet) { アニメーションを実行します。 } アニメーションフレームをリクエストします(this[TICK]); }; this[TICK](); } 一時停止() {} 再開する() {} リセット() {} アニメーションを追加します。 this[ANIMATIONS].add(アニメーション); } } エクスポートクラス Animation { コンストラクター(オブジェクト、プロパティ、開始値、終了値、期間、タイミング関数) { this.object = オブジェクト; this.property = プロパティ; this.startValue = 開始値; this.endValue = endValue; this.duration = 期間; this.timingFunction = タイミング関数; } 実行(時間) { コンソールログ(時間); 範囲を this.endValue - this.startValue とします。 this.object[this.property] = this.startValue + (範囲 * 時間) / this.duration; } } デバッグを容易にするために、アニメーションの run メソッドに 最後に、main.js でタイムラインにアニメーションを追加します。 './framework.js' から Component、createElement をインポートします。 './carousel.js' から { Carousel } をインポートします。 './animation.js' から { Timeline, Animation } をインポートします。 ギャラリー = [ 'https://source.unsplash.com/Y8lCoTRgHPE/1600x900', 'https://source.unsplash.com/v7daTKlZzaw/1600x900', 'https://source.unsplash.com/DlkF4-dbCOU/1600x900', 'https://source.unsplash.com/8SQ6xjkxkCo/1600x900', ]; a = <Carousel src={gallery} /> とします。 // document.body.appendChild(a); ドキュメントの本文にマウントします。 tl = new Timeline(); // tl.add(新しいアニメーション({}, 'property', 0, 100, 1000, null)); tl.start(); アニメーションは実際に動作し、時間を取得できることがわかりました。しかし、アニメーションが止まらずに再生され続けるという問題も見つかりました。 次に、終了条件を追加する必要があります。現在の時刻がアニメーションの継続時間を超えている場合は、animation.run を実行する前に条件判断を行う必要があります。この時点でアニメーションを停止する必要があります。 まず、 エクスポートクラスタイムライン{ コンストラクタ() { this[ANIMATIONS] = 新しい Set(); } 始める() { startTime を Date.now() とします。 this[TICK] = () => { t = Date.now() - startTime とします。 for (this[ANIMATIONS]のアニメーションをlet) { if (t > アニメーション.duration) { this[アニメーション].delete(アニメーション); } アニメーションを実行します。 } アニメーションフレームをリクエストします(this[TICK]); }; this[TICK](); } 一時停止() {} 再開する() {} リセット() {} アニメーションを追加します。 this[ANIMATIONS].add(アニメーション); } } このように、複雑なロジックなしで停止条件を追加しました。最後に、main.js で Animation の最初のパラメータを変更します。渡されたオブジェクトにセッターを追加すると、アニメーションで時間を出力できるようになります。これによりデバッグが容易になります。 tl.add( 新しいアニメーション( { 設定a(a) { コンソールにログ出力します。 }, }, '財産'、 0, 100, 1000, ヌル ) ); アニメーションは確かに停止していることがわかりますが、まだ問題が残っています。アニメーションの継続時間を 1000 ミリ秒に設定しましたが、最後の値は 1002 ミリ秒であり、明らかにアニメーションの継続時間を超えています。 したがって、アニメーションの終了条件に遭遇したときは、その期間 (アニメーション期間の値) をアニメーションに渡す必要があります。ここでは次のように記述します。 始める() { startTime を Date.now() とします。 this[TICK] = () => { t = Date.now() - startTime とします。 for (this[ANIMATIONS]のアニメーションをlet) { t0 = t とします。 if (t > アニメーション.duration) { this[アニメーション].delete(アニメーション); t0 = アニメーションの継続時間; } アニメーションを実行します。 } アニメーションフレームをリクエストします(this[TICK]); }; this[TICK](); } 一時停止() {} 再開する() {} リセット() {} アニメーションを追加します。 this[ANIMATIONS].add(アニメーション); } } このようにして、タイムラインとアニメーションの予備機能が確立されます。 デザインタイムラインの更新次に、このタイムラインにさらに多くの機能を追加して、アニメーション ライブラリを実際に使えるようにします。 CSS アニメーションでは、継続時間 (アニメーション継続時間) があることはわかっていますが、実際には遅延 (アニメーション遅延時間) もあります。 まず、この機能を追加してみます。 Delayプロパティのサポートを追加しました開発中に、元のライブラリに機能を追加したい場合。私たちが最初に考慮するのは、「この機能を追加するのに適切な場所を見つけること」です。 実際、直感的に言えば、この関数はアニメーションの一部なので、この遅延を Animation クラスに配置するのが最初の本能です。しかし、より良いアイデアがあります。それは、タイムラインに遅延を入れることです。 アニメーションの開始時間、終了時間、および時間制御はすべてタイムライン関連の問題であり、実際にはアニメーションが重点を置いているものとは異なります。アニメーションに関しては、アニメーションの効果と操作に重点が置かれていると思います。 したがって、タイムラインに遅延を設定する方が明らかに適切です。 Timeline の 遅延ロジックを追加しながら、問題を解決することもできます。つまり、アニメーションをキューに追加すると、タイムラインがすでに実行されている可能性があります。このように、アニメーションを追加すると、アニメーションの開始時間が間違ってしまいます。 もう 1 つの問題は、start メソッドでは、 さて、遅延機能を実装するときには、これら両方の要素を考慮に入れることができます。 まず、遅延パラメータを追加しましょう。 エクスポートクラス Animation { コンストラクター(オブジェクト、プロパティ、開始値、終了値、期間、遅延、タイミング関数) { this.object = オブジェクト; this.property = プロパティ; this.startValue = 開始値; this.endValue = endValue; this.duration = 期間; this.timingFunction = タイミング関数; this.delay = 遅延; } 実行(時間) { コンソールログ(時間); 範囲を this.endValue - this.startValue とします。 this.object[this.property] = this.startValue + (範囲 * 時間) / this.duration; } } ここで行うことは、コンストラクターに タイムライン キューに追加された各アニメーションには異なる遅延がある可能性があるため、アニメーションの開始時間も異なります。したがって、すべてのアニメーションの開始時刻を保存するために、Timeline クラスのコンストラクターの下に エクスポートクラス Animation { コンストラクター(オブジェクト、プロパティ、開始値、終了値、期間、遅延、タイミング関数) { this.object = オブジェクト; this.property = プロパティ; this.startValue = 開始値; this.endValue = endValue; this.duration = 期間; this.timingFunction = タイミング関数; this.delay = 遅延; } 実行(時間) { コンソールログ(時間); 範囲を this.endValue - this.startValue とします。 this.object[this.property] = this.startValue + (範囲 * 時間) / this.duration; } } 次に、タイムラインにアニメーションを追加する add メソッドで、アニメーションの開始時間を START_TIMES データに追加します。ユーザーが add メソッドに startTime パラメータを渡さない場合は、デフォルト値 アニメーション、開始時間を追加します。 引数の長さが 2 未満の場合は、startTime を Date.now() に設定します。 this[ANIMATIONS].add(アニメーション); this[START_TIMES].set(アニメーション、開始時間); } 次に、開始時間のロジックを変換します。
コードは次のように実装されます。 始める() { startTime を Date.now() とします。 this[TICK] = () => { now = Date.now() とします。 for (this[ANIMATIONS]のアニメーションをlet) { t とします。 if (this[START_TIMES].get(アニメーション) < 開始時間) { t = 現在 - 開始時刻; } それ以外 { t = 現在 - this[START_TIMES].get(アニメーション); } t > アニメーションの継続時間の場合 this[アニメーション].delete(アニメーション); t = アニメーションの継続時間; } アニメーションを実行します。 } アニメーションフレームをリクエストします(this[TICK]); }; this[TICK](); } このように、Timline ではいつでもアニメーションを追加できます。この新しい機能のテストを容易にするために、 ここで 始める() { startTime を Date.now() とします。 this[TICK] = () => { now = Date.now() とします。 for (this[ANIMATIONS]のアニメーションをlet) { t とします。 if (this[START_TIMES].get(アニメーション) < 開始時間) { t = 現在 - 開始時刻; } それ以外 { t = 現在 - this[START_TIMES].get(アニメーション); } if (t > アニメーション.duration) { this[アニメーション].delete(アニメーション); t = アニメーションの継続時間; } アニメーションを実行します。 } アニメーションフレームをリクエストします(this[TICK]); }; this[TICK](); } webpack で再パッケージ化した後、コンソールで次のコマンドを実行して、タイムラインにアニメーションを追加できます。 tl.add(アニメーション); さて、これがタイムラインの更新されたデザインです。しかし、この時点では、アニメーションを遅延させるための delay パラメータの値は実際には設定されていません。 実際、ここで必要なのは、 if (this[START_TIMES].get(アニメーション) < 開始時間) { t = 現在 - 開始時間 - アニメーションの遅延; } それ以外 { t = 現在 - this[START_TIMES].get(animation) - animation.delay; } ただし、特別なケースに注意する必要があります。t t > 0 の場合、アニメーションを実行します。 次に、一時停止と再開の機能を実装してみましょう。 一時停止と再開機能の実装まずは一時停止機能を追加してみます。 一時停止の実装タイムラインの一時停止機能を実装するには、まずティックをキャンセルする必要があります。つまり、私たちのタイムラインの時間は止まります。時計の秒針が止まれば、当然時間も止まります。 ティックをキャンセルするには、まずティックがトリガーされたときに何が起こっているかを知る必要があります。言うまでもなく、これは 最初に宣言した したがって、最初のステップは、TICK_HANDLER を使用して requestAnimationFrame を保存することです。ティックは Timeline クラスの start メソッドで開始されるため、ここでは start メソッドの 始める() { startTime を Date.now() とします。 this[TICK] = () => { now = Date.now() とします。 for (this[ANIMATIONS]のアニメーションをlet) { t とします。 if (this[START_TIMES].get(アニメーション) < 開始時間) { t = 現在 - 開始時間 - アニメーションの遅延; } それ以外 { t = 現在 - this[START_TIMES].get(animation) - animation.delay; } if (t > アニメーション.duration) { this[アニメーション].delete(アニメーション); t = アニメーションの継続時間; } t > 0 の場合、アニメーションを実行します。 } this[TICK_HANDLER] = requestAnimationFrame(this[TICK]); }; this[TICK](); } 次に、 一時停止() { アニメーションフレームをキャンセルします(this[TICK_HANDLER]); } 一時停止は比較的簡単ですが、再開はより複雑です。 履歴書の実装次に、再開を実装するための最初のステップは、ティックを再起動することです。しかし、tick の t (アニメーション開始時間) は明らかに間違っているので、一時停止のロジックを処理する方法を見つける必要があります。 Resume を実装する前に、DOM をいくつか操作してテストする必要があります。まず新しい HTML を作成し、その中に <!-- 新しい animation.html を作成します (dist フォルダーに配置します) --> <スタイル> 。箱 { 幅: 100ピクセル; 高さ: 100px; 背景色: 水色; } </スタイル> <本文> <div class="box"></div> <script src="./main.js"></script> </本文> そうすると、 // ルートディレクトリに `animation-demo.js` を作成します './animation.js' から { Timeline, Animation } をインポートします。 tl = new Timeline(); tl.start(); tl.add( 新しいアニメーション( { 設定a(a) { コンソールにログ出力します。 }, }, '財産'、 0, 100, 1000, ヌル ) ); ページで使用されている js エントリ ファイルを変更したためです。そこで、 モジュール.エクスポート = { エントリ: './animation-demo.js', モード: '開発'、 開発サーバー: { コンテンツベース: './dist', }, モジュール: { ルール: { テスト: /\.js$/, 使用: { ローダー: 'babel-loader', オプション: プリセット: ['@babel/preset-env'], プラグイン: [['@babel/plugin-transform-react-jsx', { プラグマ: 'createElement' }]], }, }, }, ]、 }, }; 現在、JavaScript はシミュレートされたアニメーション出力です。次に、アニメーションに要素を操作する機能を追加してみます。 まず、スクリプト内でこの要素を取得しやすくするために、要素に <div class="box" id="el"></div> 次に、このプロトタイプをアニメーション化します。まず、 次に、2 番目のパラメータのプロパティが したがって、変換 ここでのテンプレート値は関数として直接記述されます。 v => `translate(${$v}px)`; 最終的に、コードは次のようになります。 tl.add( 新しいアニメーション( document.querySelector('#el').style, '変身'、 0, 100, 1000, 0, ヌル、 v => `translate(${v}px)` ) ); この部分を調整した後、animation.js に移動して対応する調整を行う必要があります。 最初のステップは、Animation クラスのコンストラクターにテンプレート パラメーターを追加することです。他のプロパティと同様に、これはコンストラクター内の単なるストレージ操作です。 次に、アニメーションの run メソッドで、 エクスポートクラス Animation { コンストラクタ( 物体、 財産、 開始値、 終了値、 間隔、 遅れ、 タイミング関数、 テンプレート ){ this.object = オブジェクト; this.property = プロパティ; this.startValue = 開始値; this.endValue = endValue; this.duration = 期間; this.timingFunction = タイミング関数; this.delay = 遅延; this.template = テンプレート; } 実行(時間) { 範囲を this.endValue - this.startValue とします。 this.object[this.property] = このテンプレート( this.startValue + (範囲 * 時間) / this.duration ); } } 最終的な効果は次のようになります。 要素のアニメーションを制御するために、すでにアニメーション ライブラリを使用できることがわかりました。 まず、これらのアニメーションのパラメータを調整し、開始位置と終了位置を 0 ~ 500 に変更し、アニメーションの継続時間を 2000 ミリ秒に変更します。この設定は、次の機能のデバッグに役立ちます。 tl.add( 新しいアニメーション( document.querySelector('#el').style, '変身'、 0, 500, 2000年、 0, ヌル、 v => `translate(${v}px)` ) ); さて、次に一時停止ボタンを追加しましょう。 <本文> <div class="box" id="el"></div> <button id="pause-btn">一時停止</button> <script src="./main.js"></script> </本文> 次に、animation-demo.js に戻ってこの要素をバインドします。そして、タイムラインで一時停止メソッドを実行させます。 document.querySelector('#pause-btn').addEventListener( 'クリック'、 () => tl.pause() ); 一時停止関数がOKであることがわかりますが、このアニメーションをどのように再生する必要がありますか?つまり、履歴書の機能を実装することです。 この履歴書関数のロジックを実装する前に、まず同じ方法で履歴書ボタンを作成します。このボタンをタイムラインの <! - animation.html-> <本文> <div class = "box" id = "el"> </div> <button id = "Pause-btn"> Pause </button> <button id = "resume-btn"> resume </button> <script src="./main.js"></script> </本文> // resumeボタンのイベントバインディングをAnimation-demo.jsに追加します。 document.queryselector( '#resume-btn')。addeventlistener( 'クリック'、 ()=> tl.resume() ); 上記の論理によれば、履歴書の最も基本的な理解は、ダニを再開することです。次に、履歴書方法で 再開する() { この[ティック](); } アニメーションでは、履歴書でティックを直接実行すると、アニメーションを再起動するボックスが元の一時停止位置でアニメーションを再生し続けないことがわかります。代わりに、彼は後ろにジャンプしました。 明らかに、履歴書をクリックしたとき、私たちのアニメーションは、私たちが一時停止したときにどこにいたかを覚えていませんでした。したがって、アニメーションを一時停止している間、開始時間を記録し、 これらの2つの変数はアニメーションクラスで使用する必要があるため、ここでグローバルな範囲で定義する必要があります。次に、2つの定数 const pause_start = symbol( 'pause-start'); const pause_time = symbol( 'Pause-Time'); 次に、一時停止する時間を記録します。 一時停止() { この[pause_start] = date.now(); CancelAnimationFrame(this [tick_handler]); } 実際、一時停止の開始時間を記録するのはなぜですか?アニメーションをいつ再生し続けるかを知るのはどれくらいの期間かを知ることです。 アニメーションで見たばかりの現象は何ですか?ティックを再起動するときであり、アニメーションの開始時間は現在の時間を使用します。ここで言及されている「現在の」時間は、タイムラインがすでになくなっている場所です。明らかに、この開始時間が正しくありません。 一時停止している瞬間の時間を記録する場合。次に、履歴書をクリックしたときにクリックする時間から持続時間を計算します。このようにして このアルゴリズムを使用して、アニメーションを元の一時停止位置で再生し続けることができます。 次に、コードロジックの実装方法を見てみましょう。 次に、時間録画の論理に一時停止を追加しました。一時停止時間を記録する前に、この値0に初期値を割り当てる場所が必要です。 最良のことは、タイムラインの開始時にこのデフォルト値を与えることです。 Pause_timeの初期値の後、履歴書を実行すると、
そのため、Pause_Timeに値を割り当てるとき、割り当てをオーバーライドする代わりに 最後に、私たちが変換したタイムラインは次のようなものです。 エクスポートクラスのタイムライン{ コンストラクタ() { この[animations] = new set(); この[start_times] = new Map(); } 始める() { startTime を Date.now() とします。 この[pause_time] = 0; この[tick] =()=> { now = Date.now() とします。 for(この[アニメーション]のアニメーションをレット){ tをしましょう。 if(this [start_times] .get(animation)<starttime){ t = now -starttime -animation.delay -this [pause_time]; } それ以外 { t = now -this [start_times] .get(animation) - animation.delay -this [pause_time]; } if(t> animation.duration){ この[アニメーション] .delete(アニメーション); t = animation.duration; } if(t> 0)animation.run(t); } この[tick_handler] = requestAnimationFrame(this [tick]); }; この[ティック](); } 一時停止() { この[pause_start] = date.now(); CancelAnimationFrame(this [tick_handler]); } 再開する() { この[pause_time] += date.now() - this [pause_start]; この[ティック](); } reset(){} add(animation、starttime){ if(arguments.length <2)starttime = date.now(); この[アニメーション] .Add(アニメーション); この[start_times] .set(animation、starttime); } } コードを実行して、それが正しいかどうかを確認しましょう。 このようにして、一時停止と履歴書の関数を完了しました。 ここでは、利用可能なタイムラインのタイムラインを実装します。 あなたが開発者である場合、個人的なブログを作成することも履歴書のハイライトです。そして、あなたが超クールなブログを持っているなら、それはさらに明るくなり、光沢があります。
これは、タイムラインとアニメーション効果(フロントエンドのコンポーネント化)を実装するための記事です。 以下もご興味があるかもしれません:
|
<<: Dockerでnginxを実行し、ローカルディレクトリをイメージにマウントする方法
>>: Win7x64でのMySQL 5.7.18解凍版のインストール方法
nginx の概要nginx は、無料のオープンソースの高性能 HTTP サーバーおよびリバース プ...
序文最近、高可用性プロジェクトに取り組む際には、データの同期が必要になっています。ノードが 2 つし...
新しいserver.jsを作成する糸初期化 -y 糸を追加エクスプレスノードモン -D var ex...
目次行と列の変換トランスクリプトの構成を分析するvue3 + el-table で作成されたトランス...
これはかなり前に書かれた記事です。今となっては、その中の考え方は学ぶ価値があるように思えます。jb5...
序文最近は、PC、iPad、携帯電話、スマートウォッチ、スマートテレビなど、さまざまなデバイスが存在...
私たちのベテランの先人たちは、数え切れないほどのコードを書き、数え切れないほどの落とし穴に陥ってきま...
src と href には違いがあり、混同される可能性があります。 src は現在の要素を置き換える...
この記事の例では、カウントダウン機能を実装するためのVueの具体的なコードを参考までに共有しています...
jQueryプラグインの毎日の積み重ねメニュー、参考までに、具体的な内容は次のとおりです。スタックメ...
コード:コードをコピーコードは次のとおりです。 <!DOCTYPE html PUBLIC &...
目次序文成果を達成するコードCSSコードJSコードHTMLコードデモンストレーションのプロセス序文ク...
1. Vueプロジェクトのパッケージ化開発されたvueプロジェクトに次の名前を入力し、パッケージ化し...
MySQL の全体的なアーキテクチャは、サーバー層とストレージ エンジン層に分かれています。サーバー...
MySQL Binログデータの回復: 誤ってデータベースを削除した場合前書き: テスト マシンで誤っ...