JavaScriptを使用してパフォーマンスの高い「ビューポートディメンションを取得」ミニアプリを作成する
初心者向けで実用的なVanillaJavaScriptチュートリアル。重要なポイント:高性能ウィンドウイベントの書き方 ユーザーのハードウェアを破壊することはありません。
対象:完全な初心者から中級者
今日は、「ビューポートディメンション」と呼ばれるすばらしい小さなアプリを作成しています。 この機能は非常に効果的です。ブラウザウィンドウのサイズを変更すると、ブラウザのビューポートの幅と高さの値が表示されます。
レスポンシブデザインを行う場合、これは非常に貴重なツールです。 CodePenにも同様の機能があります。しかし、もっと大きなものといくつかの追加機能が必要だったので、自分で作成することにしました。その過程で、特にパフォーマンスの問題を処理する方法について、たくさんのことを学びました。今、私はあなたとそれを共有しています!
ビューポートの寸法
私はあなたの既存の知識について推測したくありません。結果として、これは非常に詳細な チュートリアル。
技術トピック:
-
createElement()
を使用して要素を作成する方法 メソッド。 Styleオブジェクト
を使用して要素のスタイルを設定する方法- ウィンドウオブジェクトの
resize
を設定して使用する方法 イベント。 -
innerWidth
を使用して、ブラウザのビューポートから幅と高さを取得する方法 およびinnerHeight
プロパティ。 - 関数の外部で関数を呼び出す方法(コールバック)。
- 条件付き(true / false)
if
ステートメントは機能します。 -
setTimeout()
を使用して、タイマーでコードの実行を遅らせる方法 -
clearTimeout()
を使用してタイマーをリセットする方法 。 - イベントスロットル機能の使用方法 ウィンドウイベントのパフォーマンスを劇的に向上させるため。
- MSとFPSの関係 (ミリ秒と1秒あたりのフレーム数)
- 知覚されるパフォーマンスの重要な違い およびハードウェアパフォーマンス。
アプローチ
ビューポートディメンションアプリの2つのバージョンを作成しています。
- バージョン1 アプリを機能させることです。これはドラフトですが、最終製品ではありません。
- バージョン2 バージョン1を改善することです。コードのパフォーマンスを高め、エネルギー効率を高め、読みやすくする方法を学びます。
JavaScript中心の状態を維持するために、すべてを実行します JavaScriptコードで。すべてを1つのJavaScriptファイルに保存することで、アプリを既存のプロジェクトに簡単に追加することもできます。
あなたは完全な初心者ですか? 次に、CodePenを使用してフォローすることをお勧めします。使用するためにサインアップする必要はありません。ここで視聴できる非常に人気のあるCodePenビデオチュートリアルを公開しました。
学ぶ方法
混乱している場合は、数段落前に戻って、重要なことをスキップしていないことを確認してください。自分で問題を解決しようとすることで、より多くのことを学ぶことができます 次に、参照コード second を探します 。
迷子になった場合 完成したコードはいつでも参照できます:
- バージョン1
- バージョン2
始めましょう!
ビューポートの寸法[バージョン1.0]
コーディングを始める前に、プロジェクトの要件を見てみましょう。
要件
- ウィンドウの幅と高さを表示するためのコンテナが必要です。
- ウィンドウの右上隅に配置する必要があります。
- デフォルトで非表示にする必要があります。
- ウィンドウのサイズが変更されるとすぐに表示されます。
- 最新のウィンドウサイズ変更から3秒後に非表示になります。
これがバージョン1の機能要件の本質です。
コーディングを始めましょう!
ディスプレイコンテナの作成とスタイリング
まず、 createElement
を使用して、ビューポートディメンションアプリのdiv要素を作成しましょう。 メソッドとそれを変数に割り当てます:
var viewportDimensions = document.createElement("div");
これで、空の
ができました。 変数内に格納されている要素。
ブラウザでは、すべてのHTML要素は要素オブジェクトで表されます。 これらのElementオブジェクトにはプロパティがあります およびメソッド JavaScriptでアクセスできます。
ビューポートの幅と高さをブラウザウィンドウの右上隅に表示する必要があります。それを処理し、HTML DOMStyleオブジェクトにアクセスしてdiv要素にスタイルを設定しましょう。 プロパティ:
viewportDimensions.style.position = "fixed";
viewportDimensions.style.right = "0";
viewportDimensions.style.top = "0";
viewportDimensions.style.padding = "16px";
viewportDimensions.style.zIndex = "3";
viewportDimensions.style.fontSize = "22px";
上記の構文はドット表記です。 簡単に言うと、。
を使用することを意味します。 オブジェクトのプロパティまたはメソッドにアクセスします。したがって、上記の例では、次のように言っています。
- ねえ
viewportDimensions
スタイルオブジェクト
へのアクセスを許可してください- そのため、スタイリングプロパティにアクセスできます
Styleオブジェクトを使用したスタイリングは、CSSを使用したスタイリングに似ています。ただし、Styleオブジェクトはインラインスタイルを使用します。 スタイリングプロパティは、外部のCSSスタイルシートではなく、HTML要素に直接追加されます。
ビューポートの寸法
まず、ドキュメントのbody要素への参照を格納する変数を宣言しましょう。 JavaScriptファイルの先頭に次のコードを追加します。
次に、body要素内にビューポートディメンションのdiv要素を追加しましょう。 JavaScriptファイルの最後(最後のスタイルの下)に次のコードを配置します:
div要素にはまだコンテンツが含まれていないため、現在のコードが機能するかどうかを確認することはできません。要素に一時的な境界線を追加することで、すぐにわかります:
正常に機能する場合は、ウィンドウの右上隅に太い黒の境界線が付いた小さなボックスが表示されます。
ブラウザウィンドウを右クリックして確認することもできます。次に、検査をクリックします ブラウザのDevToolsにアクセスします。
次に、[要素]タブで、
これまでのすべてのコードの概要は次のとおりです。
すばらしいです。div要素が作成され、スタイルが設定され、body要素内に追加されました。次はウィンドウサイズ変更イベントです。
Windowオブジェクトは、ブラウザウィンドウを表します。
注:コメント
以前は、ドット表記を使用してdiv要素のプロパティを取得しました。これを使用して、メソッドにアクセスします。 ウィンドウオブジェクト:
2つの引数を渡します イベントリスナーへ:
ウィンドウイベントを呼び出すたびに、
動作していることを確認するために、
次に、ウィンドウのサイズを変更します。コンソールに「Working!」と表示された場合何度も、それはあなたのウィンドウサイズ変更イベントが機能していることを意味します。
CodePenでコンソールにアクセスするには、ウィンドウの左下隅にある[コンソール]ボタンをクリックします。 Chromeでコンソールにアクセスするには、キーボードショートカットを次に示します。
了解しました。ウィンドウイベントを機能させましょう!
次の動きは、ビューポートの幅と高さの数値を取得することです。ウィンドウのサイズを変更するときに、値を即座に更新する必要があります。 ウィンドウオブジェクト ブラウザウィンドウを表します。
彼らが何をしていると思いますか?
はい、ブラウザウィンドウの幅と高さをピクセル単位で返します(スクロールバーを含む)。これを確認して、
現在の値を動的に取得する必要があるため
実際には、
それが機能する場合、ブラウザウィンドウのサイズを変更する限り、コンソールは常に現在のビューポートのサイズを印刷します。
次のようになります:
今、私たちはどこかに到達しています!
今
新しい変数が正常に機能することを確認するには、それらの新しい変数をコンソールに出力してみてください。
すべてが機能する場合は、console.logを削除して、次に進むことができます。
返された幅と高さの値をdiv要素に追加します。具体的には、値を内部に埋め込みます。 div要素の開始タグと終了タグ:
これを行うには、div要素を格納する変数
次に、幅と高さの変数を割り当てる必要があります。
今すぐブラウザウィンドウのサイズを変更してみてください。すべてを正しく行うと、ウィンドウの右上隅に現在の幅と高さの値が表示されます。
上で使用したコード構文は少し混乱しているように見えるかもしれません。
分解してみましょう:
一部のテキスト...
ウィンドウのサイズを変更していないときに、幅と高さが常に表示されることは望ましくありません。ブラウザウィンドウのサイズ変更を停止してからちょうど3秒後に、ビューポートの寸法のdiv要素が消えるようにしましょう。
これを行うには、ウィンドウオブジェクトの別のメソッドを使用する必要があります 、
これは次のように機能します:
1000ミリ秒=1秒。したがって、上記の3000は3秒を意味します。
どの関数を実行しますか? ビューポートディメンションのdiv要素を削除するもの。
そのような関数はまだありません。作成して
次のコードを上記に追加します ウィンドウイベント関数:
次に、電話する必要があります 新しい
これで、ウィンドウのサイズ変更イベントがアクティブになるたびに、
3秒が経過すると、
これで、div要素のdisplayプロパティが
div要素が削除された直後に、ブラウザウィンドウのサイズをもう一度変更しようとすると、div要素は再び表示されません。 最後だからです プログラムで発生するのは、div要素が
プログラムのどこにも、div要素を再び表示したいと述べているところはありません。
しかし、なぜ初めて表示されたのですか? デフォルトでは
div要素に対して行う最後のことは、その表示値を
これは簡単に修正できます。ウィンドウサイズ変更イベントのコードブロック内(
これで、div要素の
素晴らしい、私たちのアプリは動作します!
まあ..ある種。別の問題があります。 ブラウザウィンドウのサイズを長時間(3秒以上)変更しようとすると、div要素がちらつき始めます。まるでライトが絶えずオン/オフされているかのようです。
これは、カウントダウンタイマーをリセットしていないために発生します。ビューポートのサイズを変更するたびに、windowイベントはその関数コードブロックを可能な限り何度も実行します。したがって、
これにより、アプリで多数の重複するコードが実行されます。私たちのdiv要素は
これにより、div要素が常に表示および非表示になり、ちらつきが発生します。これは最悪だ。この問題を解決するには、タイマーをクリアする方法を学ぶ必要があります。 JavaScriptで動作します。
既存のタイマーをクリアすることは、まさに私たちが望んでいることです。
しかし、それはうまくいきません。 clearTimeout()メソッドを使用するには、グローバルを使用する必要があります タイムアウトメソッドを作成するときに変数。
JavaScriptには、グローバルとローカルの2つのスコープがあります:
これは、
グローバル変数を作成して、
この変数をJavaScriptファイルの一番上に配置します。
今のところ、それは単なる空の変数です。サイズ変更イベントが最初に開始されるまで、空になります。
次に、
これで、グローバルな
これで、
では、サイズ変更イベントを5〜6秒間実行すると、ちらつきがなくなったことがわかります。
混乱していますか? コードで何が起こるかについて話しましょう。
JavaScriptインタープリター(ブラウザーで実行されるエンジン)がコードを読み取り、次のことを行います。
ウィンドウのサイズを変更し続ける限り、コードは上から下に実行され続けます。サイズを少し変更するたびに、新しいウィンドウイベントが発生します。そのため、JavaScriptインタープリターは、コードを1秒間に何度も読み取り、実行します。
ウィンドウイベントの関数がそのコードブロックを実行するたびに、
最後 コード行に、
したがって、最後に発生するのは常に 1
素晴らしい!バージョン1が完了しました。ここで完全なコードを表示できます。バージョン2に移りましょう。ここでは、特にパフォーマンスに焦点を当てます。
私たちのアプリは動作しますが、それで十分ですか?その質問に答えるには、2つの重要なことを考慮する必要があります。
UXの観点から、私たちのアプリは素晴らしいパフォーマンスを発揮すると思います。応答時間が非常に速く、古い画面でも非常によくレンダリングされます(私は数十年のベテランでテストしました)。ビジュアルの最適化(UIデザイン)についてはいつでも議論できます。しかし、純粋な機能に基づいて、私たちのアプリはうまく機能します。
しかし、ハードウェアのパフォーマンスから 視点から見ると、私たちのアプリは本当に 悪い。私たちのアプリは、その技術的要件がいかに控えめであるかと比較して、大量のCPUおよびGPUリソースを使用しています。
理由がわかりますか? ごみ遣いに慣れていないときに、本能的に考えることではありません。 ウィンドウイベントの。
問題は次のとおりです:
ブラウザウィンドウのサイズを変更するたびに、アプリのウィンドウイベントはその関数を数百回実行しています。 ほんの数秒で!
問題を視覚化する関数をCodePenに配置しました。 1秒間に実行される関数の数に注意してください。また、屋根を吹き抜ける総数をすばやく確認してください:
CodePenの例
これは恐ろしく、まったく不要です!私たちのコードは、本来よりもはるかに多くのリソースを使用しています。
ブラウザイベント中にCPUとGPUがどの程度機能しているかを確認するには、Chromeのタスクマネージャを起動します。
ブラウザウィンドウのサイズを変更してみてください。タスクマネージャー内では、アクティブなブラウザータブの横にCPUとGPUの使用率が返されます。
ハードウェアの絶対使用量と相対使用量を区別することが重要です。絶対的な(全体的な)ハードウェア使用の観点から、私たちの小さなアプリはそれほど害を及ぼしません。ほとんどのコンピューターは非常に強力なので、これに動揺することはできません。
しかし、相対から 使用法の観点から、私たちのアプリはひどく非効率的です。そしてそれが問題です。パフォーマンスを無視する習慣を身につけたくはありません。パフォーマンスが私たちを悩ませ、お尻に噛み付くために戻ってくるからです。
重いを実行するアプリケーションの操作を開始するとすぐに 機能、ハードウェアの使用は深刻な問題になります。今のようにコードを実行すると、見栄えが悪くなります。
デフォルトでは、標準のウィンドウイベントは、イベントがアクティブである限り、可能な限り多くの関数を実行します。小さな変更があるたびに、新しいウィンドウイベントがトリガーされます。これが、私たちのアプリが現在持っている途方もなく高い実行率の原因です。
関数は1秒間に何回実行されますか?
4ミリ秒ごとから40ミリ秒ごとのいずれかになります。これは、次のような多くの要因によって異なります。
ハードウェアは、特定の時間に利用可能なリソースを使用して、何かを実行するように要求します。
無料が足りない場合もあります 大量のアプリが同時に実行されているため、リクエストにすぐに対応するためのリソース。
これにより、応答時間が遅くなり、画面の不具合、フリーズなどの問題が発生する可能性があります。
ハードウェアの使用量が増えます。 これが、アプリケーションの現在の状態を修正する必要がある理由です。パフォーマンスを重視しているからです!
注:最新のブラウザでは、最小実行速度は4msです フレームレートの観点からは約250fpsです。これは、MozillaのWebAPIドキュメントによるものです。
ただし、このトピックについては矛盾する情報があります。詳細については、こちらをご覧ください。
関数を「実行する」頻度はどれくらいですか?
理想的な関数の実行率は、コンテキストによって異なります。詳細なアニメーションを使用していますか?または、(アプリで行うように)いくつかの数値を返すような単純なものですか?
コンテキストに関係なく、通常、ウィンドウイベントで関数をできるだけ多く実行することは望ましくありません。それはばかげています。また、無料ではありません。やめなきゃ!
スロットリングと呼ばれるプロセスを使用して、実行頻度を制御できます。 それは次に来るでしょう。
スロットル機能を使用できます 別の回数を制限する 関数は時間の経過とともに実行されます。例:「この関数は100ミリ秒に1回だけ呼び出す」
ウィンドウのサイズ変更イベントによってトリガーされる基本的なイベントスロットル関数を見てみましょう。その後、スロットルは100ミリ秒ごとに外部関数を呼び出します。
読みやすくするために、コードの書式設定に空白を追加しました。コードを数回読んで、理解できるかどうかを確認してください。
このCodePenを使用してテストします。
最大と言います 関数は、設定した速度で常に正確に起動するとは限らないためです。これは、関数の実行時にハードウェアがどれだけビジーであるかによって異なります。コンピューターで他のエネルギー課税アプリを実行していますか?。
これを初めて理解しなくても心配しないでください。最終的にクリックされるまで、私はこのようなものをいじくり回すのに多くの時間を費やしました。
JavaScriptファイルの一番上で、2つのグローバルを宣言することから始めます。 変数:
注:グローバル 変数は、どこからでもこれらの変数にアクセスできることを意味します。
デフォルトでは、空の変数の値の型は
次に、
私はせいぜいと言います 100msは実行率に上限を設けるからです。ユーザーのハードウェアとソフトウェアによっては、実際には1秒あたり10回未満の関数呼び出しを受け取る場合があります。ただし、ほとんどのコンピューターは1秒間に10回起動できます。
スロットル関数内で、条件付きの
条件文は、指定された条件に真の値があるかどうかをチェックします。
「スロットルされた場合は 真の値を持っている場合は、
「しかし、
JavaScriptのTrueとFalseの値は何ですか?
JavaScriptには、真実があります および偽り 値。うん、それは彼らが呼ばれているものです。真実は真実である価値です。 Falsyは、falseと見なされる値です(驚きです!)。
JavaScriptには、6つの偽の値があります。
In JavaScript, anything that is not one of the above values is considered a truthy value. That’s pretty simple, right?
With that quick lesson on true vs. false, go ahead and check if our
We can quickly find out with
Great, now we have confirmed that
Which means that we can move onto what happens inside
Once inside the
We also set our global throttled variable to true, so it’s no longer
But then right below, we use
So every time the window resize event is running, it triggers the
It’s easier to understand how powerful throttling is if you look at two opposite extremes. Try the following in the throttler function on CodePen:
That’s how throttling works. We use it to limit the number of times a function can be called over time. It’s a very easy way to avoid wasting hardware resources. The hard part is finding the “optimal” execution rate for a given function, as no project is the same. More about that later.
To apply the throttler function to our own project, we’ll need to do a bit of refactoring to the old code first. Refactoring is when we improve the structure of a program but don’t change the overall functionality.
In other words:we take something that already works, and makes it easier to use and understand.
We no longer want the window resize event to directly execute the function that returns width and height. Instead, we want our throttler function to regulate when and how often the code executes.
Fortunately, the change is simple. We just need to declare a named function and then put all code from the anonymous function inside that named function.
Let’s call the new function
Now let’s take the same throttler function from earlier, and replace the
And finally we add the window resize event listener:
That’s it, all the hard work is done! Before we wrap up, let’s check our app’s performance, and see if we need to tweak anything.
I don’t know about you, but when I resize my browser window, the width and height numbers are rendering a bit laggy to my screen. It’s not as smooth as it was before we added the throttler.
But that’s not surprising. Before we added the throttler, our code’s execution rate was absurdly high. Now it’s firing around 10 times per second. That’s why it’s a bit laggy now.
There’s no doubt that our app is very performant, from a hardware usage perspective. Our hardware hardly does any work, so it absolutely loves us right now. Which is good.
But what about the perceived performance, from the User Experience point of view? Do our users love us too?
Our rendering should be smoother. Our function execution rate is currently capped at 10 times per second. Let’s increase it. But how much?
We can make it easier to make that decision if we first take a look at the relationship between time and frame rate.
Frame rate is also known as FPS (Frames Per Second). It refers to the number of individual frames displayed per second.
In general, the higher fps the smoother the rendering will be. Video games often need 60fps or more to render smoothly. Most movies and tv series run smoothly at 24-30fps. The more fast-paced action a video or graphic has, the more FPS it needs to render smooth.
For some types of graphics, you can go as low as 15fps and still get a smooth render. But you should rarely go below 15fps because then the perceived performance will start to look noticeably slower.
To find your desired FPS in ms, you divide your target fps with 1000, e.g. 1000/15(fps) =66ms.
Take a look at this FPS to millisecond table:
Do you recognize something? Our app is currently executing every 100ms, or in frame rate terms:10 frames per second.
Remember, I just said that anything below 15fps will usually appear slow? That could explain why current app’s rendering feels a bit off. There are not enough frames per second to render it smooth. It doesn’t feel instant.
I’ll guarantee that if we crank our Viewport Dimensions feature up to run at 15fps (66ms), it will look significantly smoother than at the current 10fps (100ms).
And it won’t cost too much extra CPU power.
We only need it to be smooth enough.
Like I said earlier, testing opposite extremes is a good way to find out what not する。 Then the question becomes where between the two extremes does your project fit?
Try testing the following frame rates:5fps (500ms), 15fps (66ms), and 60fps (16ms) on your Viewport Dimensions app and see what happens.
What do you think?
5fps looks horrible. It looks broken. That would never work. Our hardware would love it, but our users will hate it!
15fps looks good to me. I wouldn't say that this frame rate is 100% smooth, but it’s clearly better than 10fps.
It’s also important to remember that if your eyes are trained to look for small details, it’s not comparable to the average user’s experience. Most people will consider 15fps smooth, for this type of graphic.
60fps is super smooth — not surprisingly. But honestly, it’s not worth massively extra hardware usage.
I’m going to settle at 15fps for my app.
The reason I decided on 15fps / 66ms, is because that frame rate is high enough to be perceived as smooth (for most people).
Most software, computers, and displays (screens) can render at 15fps without problems. Even most small, handheld devices can handle 15fps without issue.
The irony of high frame rates is that while logic tells us that more frames per second =smoother, it can also have the opposite effect.
If you try to force a frame rate or refresh rate that your user’s hardware and software can’t handle, the result is often:lagging.
Refresh rate :is how many times your display can redraw your screen. A refresh rate of 45Hz means that your display can redraw it’s entire screen 45 times in 1 second.
Now if your CPU &GPU can generate a frame rate of 60fps, but your display’s refresh rate is only 45Hz, then you have a mismatch. This often causes unpredictable results.
We developers and designers can easily get out of touch with reality. Our development machines are usually more powerful than the average person’s computer.
This is why we need to do solid research and test our assumptions before we push products on the market.
So 15fps is a happy medium that will also work for people who don’t have powerful machines.
Using 15fps will also save us at least 75% of the energy our hardware used before we added the throttler.
Anything below 15fps will usually start to look slow and laggy. It becomes really obvious once you get to around 10fps, which is why our initial frame rate wasn’t good enough.
Here’s an insightful video on the topic of response times which supports my argument for not going below 15fps (on most things).
How much of a perceived difference is there from 15 to 30fps? If you test it out on the app we just built, you’ll be surprised.
You probably won’t be to notice any significant difference. Not a deal-breaking 違い。 But the price you pay for hardware usage is double up!
High fps costs a lot of hardware power. So why use more than necessary? There’s always a point of diminishing returns. That’s where the Minimum Effective Dose (MED) comes in. You only need enough, to get the desired effect, no more, no less.
Of course, it always depends on the context. Are we talking about an explosive first-person shooter video game or a simple pixel counter like the one we’ve built? Context is key!
All the hard work is done. For good measure, let’s wrap all our code inside an IIFE (
IIFE (Immediately-Invoked Function Expression), keeps all your code inside a local scope.
If we don’t wrap our code like this, we risk “polluting the global namespace”. This is a fancy way of saying that we risk causing conflicts with other code, outside of our app.
Here is all the code we’ve written. I've added some comments for clarification and some extra white space for readability:
Here’s a CodePen you can play with.
Include a script tag at the bottom of your HTML document, just above your closing body tag (
Our app is compatible with all modern browsers, and from Internet Explorer 9 and up.
What we learned in this tutorial is a great precursor for some the more powerful performance tools on the market.
If you need to boost performance on more complex projects than the one we built, check out the Lodash JavaScript library. Lodash has a lot of performance features and is very popular among developers. You can also learn a lot from digging through the library’s code.
JavaScriptのcall()関数を使用すると、異なるオブジェクトから同じメソッドを使用できます。ここでは、パラメータが個別に渡されます。 以下は、JavaScript関数call()のコードです- 例 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0
JavaScriptは、プロトタイプに基づくオブジェクトベースの言語です。継承は、プロトタイプオブジェクトを使用してJavaScriptで実装されます。 以下は、JavaScriptで継承を実装するためのコードです- 例 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-sc
への要素 HTMLドキュメントの要素。 var body = document.querySelector("body");
body.appendChild(viewportDimensions);
appendChild()
メソッドです 別のノード内にノードを追加(追加)します。 すべて DOMにはノードがあり、さまざまな種類のノードがあります。この場合、body要素ノード内にdiv要素ノードを追加します。viewportDimensions.style.border = "10px solid";
body
を見つけます。 要素を指定すると、いくつかのインラインスタイルプロパティを含む空のdiv要素が表示されます。// Select body element
var body = document.querySelector("body");
// Create div element
var viewportDimensions = document.createElement("div");
// Style element
viewportDimensions.style.position = "fixed";
viewportDimensions.style.right = "0";
viewportDimensions.style.top = "0";
viewportDimensions.style.padding = "16px";
viewportDimensions.style.zIndex = "3";
viewportDimensions.style.fontSize = "22px";
// Add div element inside body element
body.appendChild(viewportDimensions);
ウィンドウサイズ変更イベントの設定
addEventListener
を含むいくつかのメソッドがあります 。このメソッドは、多くのタイプをリッスンできます。 スクロール、クリック、入力、サイズ変更などのウィンドウイベントの一覧。'resize'
を使用します イベント。 body.appendChild
の下 以下を追加します:window.addEventListener("resize", function() {
// Code to execute when window resizes
});
//
ブラウザによって解釈されるのではなく、私たち人間のためだけに存在します addEventListener
。'resize'
およびfunction()
。サイズ変更イベントについてはすでに説明しましたが、その機能は何ですか? function()
ウィンドウサイズ変更イベントがアクティブになるたびに(ウィンドウのサイズを変更するとすぐに)実行するコードブロックを設定します。コードブロックは、中括弧 {}
の中にあるものです。 (機能本体とも呼ばれます) これまでのところ、//コメント
しかありません 。 function()
に通知します。 中括弧内のコードを実行するには{}
。 console.log()
を使用してテストしてみましょう。 :window.addEventListener("resize", function() {
// Code to execute when window resizes
console.log("Working!");
});
コンソールへのアクセス
ブラウザの幅と高さをピクセル単位で返す
innerWidth
と呼ばれるいくつかの素晴らしいプロパティがあります およびinnerHeight
。 console.log()
を使用しましょう これらの幅と高さのプロパティ値を返します。 console.log()
を配置する必要があります は、サイズ変更イベントの機能ブロック内にあります:window.addEventListener("resize", function() {
// Code to execute when window resizes
console.log("Width:", window.innerWidth);
console.log("Height:", window.innerHeight);
});
'幅:'
および'Height:'
console.log()
のテキスト は、コンソール出力を明確にするためだけにあります。window。
を作成する必要はありません。 幅と高さの値を取得するには、 innerWidth
およびinnerHeight
動作します。混乱を避けるためにそうします。 console.log()
を取り除きましょう 代わりに、widthプロパティとheightプロパティを独自の変数に割り当てて、それらへの参照を保存できるようにします。window.addEventListener("resize", function() {
// Code to execute when window resizes
var width = window.innerWidth;
var height = window.innerHeight;
});
width
およびheight
ウィンドウの幅と高さのプロパティの現在の値が常に含まれます。 常に 戻り値を変数に割り当てる必要がありますが、後でその情報を使用または変更できるため、これは良い習慣です。window.addEventListener("resize", function() {
// Code to execute when window resizes
var width = window.innerWidth;
var height = window.innerHeight;
console.log(width);
console.log(height);
});
div要素に幅と高さの値を追加する
<div> We want width & height values here </div>
viewportDimensions
を取得する必要があります。 。次に、 textContent
という要素オブジェクトのプロパティにアクセスする必要があります。 。以前と同じドット表記を使用します:viewportDimensions.textContent;
viewportDimensions.textContent = width + "px" + " x " + height + "px";
textContent
要素オブジェクトのプロパティです。ビューポートの寸法div要素を含め、ドキュメント内のすべての要素にそれがあります。 textContent
ノードを返します 具体的には、テキストノード 。例:段落要素内のテキスト:
、はテキストノードです。 viewportDimensions
変数に空のwidth + "px" + " x " + height + "px";
幅コード> および
height
どちらにもピクセル値が含まれています。 'px'
のみを追加します および'x'
(文字列)幅と高さの変数を分離し、返される値がピクセル単位であることをすべての人に明確にするため。 setTimeout()を使用したカウントダウンタイマーの追加
setTimeout
と呼ばれます 。このメソッドは、 function()
を実行するように設計されています 1回 後 指定されたミリ秒数。setTimeout(functionToExecute, 3000);
removeViewportDimensions()
と呼びましょう。 そしてそのコードブロック内{}
div要素を削除するように指示しましょう。function removeViewportDimensions() {
viewportDimensions.style.display = "none";
}
display
プロパティは、方法または if を指定します 要素が表示されます。 'none'
に設定する 、非表示にしています。removeViewportDimensions()
関数、内部から ウィンドウイベントコードブロック。 setTimeout()
の使用 以前の形式で、次を追加します:setTimeout(removeViewportDimensions, 3000);
setTimeout
3秒のカウントダウンを設定します。言い換えれば、私たちは遅延 removeViewportDimensions()
の呼び出し 3秒で。 removeViewportDimensions()
関数が呼び出され、そのコードが実行されます:'none'
に設定されました。 、および非表示になっています。しかし問題があります
display
を取得することです。 プロパティを'none'
に設定 。 display
を意味します プロパティ値は'block'
です —これは目に見える 表示タイプ。 'none'
に設定することです。 。そのため、その値はまだ 2回目にresizeイベントを実行するときは、要素上にあります。ページを更新しない限り。 setTimeout
の上)に以下を追加します !):viewportDimensions.style.display = "block";
display
プロパティは'block'
に設定されています サイズ変更イベントが実行されるたび。ウィンドウのサイズを変更し、div要素が非表示になるのを待ってから、もう一度サイズを変更してみてください。 removeViewportDimensions()
関数はまたです 何度も呼ばれます。display='none'
で打たれています プロパティおよび display ='block'
同時にプロパティ。カウントダウンタイマーのリセット
clearTimeout()
を使用して、既存のタイマーをクリアできます 方法。このメソッドは、クリアするように設計されています setTimeout
で設定されたタイマー 方法。それらはパートナーメソッドのようなものです。 setTimeout()
のみを実行します タイマー1回 サイズ変更イベントごと。 clearTimeout()
を実行できると思われるかもしれません setTimeout()
で このように:clearTimeout(setTimeout);
setTimeout()
をクリアしたい場合を意味します 最初にグローバル変数に割り当ててから、 clearTimeout()
を呼び出すことができます その変数にリセットします。 resizeTimeout
と呼びましょう。 :var resizeTimeout;
console.log(resizeTimeout)
を使用しようとした場合 未定義になります 戻ってきた。 undefined
false 重要な値型。理由はすぐにわかります。 setTimeout()
を取得します 以前の関数を使用して、 resizeTimeout
に割り当てます。 変数:resizeTimeout = setTimeout(removeViewportDimensions, 3000);
resizeTimeout
変数は、 setTimeout
に関する情報を受け取ります サイズ変更イベントがアクティブになるとすぐに機能します。 setTimeout()
を使用できます ウィンドウサイズ変更イベントが実行されるたび。 clearTimeout()
を設定します グローバルなresizeTimeout
変数。このように:clearTimeout(resizeTimeout);
resizeTimeout =setTimeout()
のすぐ上にコードを配置します したがって、次のようになります:clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(removeViewportDimensions, 3000);
clearTimeout()
既存のをリセットします resizeTimeout
でのキューのカウントダウン 変数。 setTimeout()
を割り当てます 。 resizeTimeout
に割り当てられる3秒のカウントダウン 。それ以前に開始されたカウントダウンは、 clearTimeout()
によって消去されます。 。
ビューポートの寸法[バージョン2]
絶対ハードウェア使用量と相対ハードウェア使用量
ウィンドウイベントの実行方法
イベントスロットリングで救助!
基本的なスロットル機能:
var throttled;
var delay = 100;
function functionToExecute() {
console.log("Executed!");
}
function throttler() {
if (!throttled) {
functionToExecute();
throttled = true;
setTimeout(function() {
throttled = false;
}, delay);
}
}
window.addEventListener("resize", throttler);
functionToExecute()
を呼び出すことがわかります 1秒あたり最大10回(10 x 100 =1000 ms =1秒)。スロットルコードで何が起こっているか:
var throttled; // Empty variable. Type: undefined (falsy value)
var delay = 100; // Number
throttled
を使用します throttler()
の参照ポイントとして 関数、キューに関数があるかどうかを確認します。 throttler()
の前 関数が最初にトリガーされると(サイズ変更イベントによって)、キューで実行する関数はありません。したがって、スロットル
空の変数として開始します。 undefined
です。 —これは偽り 値型。これが重要である理由がすぐにわかります。 delay
という変数に数値(100)を割り当てます。 。これは、 ms(ミリ秒)を調整するために使用する値です。 throttler()
の実行率 機能。 delay
に100msを割り当てます 変数。次に、その変数をスロットルの setTimeout()
に渡します。 。その後、スロットルは100ミリ秒ごとまたは1秒あたり10回実行されます—最大で。 if
を設定します ステートメント:function throttler() {
if (!throttled) {
// code to execute
}
}
!コード> 記号は
not
を意味します 。したがって、 if(!throttled)
次のように変換されます: if
を実行します のコード」。スロットル
の場合 します 真実の価値を持っているなら、そこでやめなさい!」
未定義
null
0
''
(空の文字列) NaN
false
Back to the throttler
throttled
variable is indeed undefined, and a falsy value type.console.log()
by using !!
to check our variable:var throttled;
console.log(throttled); // undefined
console.log(!!throttled); // false value
!!
is a double not
operation. It’s a quick way to check for truthy and falsy values.throttled
is undefined, and a falsy value type. This means that the very first time our throttler()
runs, if
’s condition is indeed met.// I start out as a falsy value
var throttled;
// I’m triggered by the window resize event
function throttler() {
// I will only run my { code } if throttled is falsy (it is!)
if (!throttled) {
// code to execute
}
}
if’s
code block.Inside if’s code block
if
statement code block, we immediately start the callback to functionToExecute
。undefined
(no longer a false value). This stops any future calls to functionToExecute()
。if (!throttled) {
// Run callback
functionToExecute();
// Set global throttled variable to true
throttled = true;
// ...
}
setTimeout
to reset the the throttled
value back to a falsy value, after the 100ms delay:function throttler() {
if (!throttled) {
// Run callback
functionToExecute();
// Set global throttled variable to true
throttled = true;
setTimeout(function() {
// Set throttled back to false after delay
throttled = false;
}, delay);
}
}
throttler()
, which will call functionToExecute
every 100ms!Throttling is power
functionToExecute()
is called (twice per second).functionToExecute()
is bombarded with calls (up to 60 calls per second).Adding the throttler to our project
getViewportDimensions()
:function getViewportDimensions() {
var width = window.innerWidth;
var height = window.innerHeight;
viewportDimensions.textContent = width + "px" + " x " + height + "px";
viewportDimensions.style.display = "block";
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(removeViewportDimensions, 3000);
}
functionToExecute()
with getViewportDimensions()
:function throttler() {
if (!throttled) {
// Callback: the function we want to throttle
getViewportDimensions();
throttled = true;
setTimeout(function() {
throttled = false;
}, delay);
}
}
window.addEventListener("resize", throttler);
Hardware Performance vs. Perceived Performance
Time vs. Frame Rate
var 2fps = 1000/2; // 500ms
var 10fps = 1000/10; // 100ms
var 15fps = 1000/15; // 66ms
var 24fps = 1000/24; // 42ms
var 30fps = 1000/30; // 33ms
var 60fps = 1000/60; // 16ms
Let’s do some testing
Why 15 FPS?
Context &the Minimum Effective Dose
A Finishing Touch
(function () {...})();
) and initialize use strict
mode inside:(function() {
"use strict";
// Put all your code below
})();
use strict;
is also used to prevent conflicts with 3rd party software that don’t follow strict coding rules.We’re done!
Finished project code:
(function() {
"use strict";
// throttled value before window event starts
var throttled;
// Delay function calls to 66ms (frame rate: 15fps)
var delay = 66;
// Declare empty variable for later use
var resizeTimeout;
// Grab body element
var body = document.querySelector("body");
// Create element
var viewportDimensions = document.createElement("div");
// Style element
viewportDimensions.style.position = "fixed";
viewportDimensions.style.right = 0;
viewportDimensions.style.top = 0;
viewportDimensions.style.padding = "16px";
viewportDimensions.style.zIndex = 3;
viewportDimensions.style.fontSize = "22px";
// Add div element inside body element
body.appendChild(viewportDimensions);
// window.resize callback function
function getViewportDimensions() {
var width = window.innerWidth;
var height = window.innerHeight;
viewportDimensions.textContent = width + "px" + " x " + height + "px";
viewportDimensions.style.display = "block";
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(removeViewportDimensions, 3000);
}
// Called from getViewportDimensions()
function removeViewportDimensions() {
viewportDimensions.style.display = "none";
}
function throttler() {
// Only run code if’s block if we’re not throttled
if (!throttled) {
// Callback: the function we want to throttle
getViewportDimensions();
// We're currently throttled!
throttled = true;
// Reset throttled variable back to false after delay
setTimeout(function() {
throttled = false;
}, delay);
}
}
// Listen to resize event, and run throttler()
window.addEventListener("resize", throttler);
// End of IFFE wrapper
})();
How to use your app on any project
) and add the path to your js file, like this:
<script src="/js/get-viewport-dimensions.js"></script>
Browser Compatibility
Advanced throttling
Resources