サイズ変更オブザーバーJavaScriptAPIの使用方法
序章
サイズ変更オブザーバーは、 Intersection ObserverAPIなどの他のオブザーバーAPIと非常によく似た新しいJavaScriptAPIです。 サイズが変更されたときに要素に通知することができます。
要素のサイズが変更される最も一般的な理由は、ビューポートのサイズが変更されたとき、またはデバイスの方向が縦向きと横向きの間で変更されたときです。 この時点まで、サイズ変更イベントをリッスンし、特定の要素のサイズが変更されているかどうかを確認するには、グローバルwindow.resize
イベントに依存する必要がありました。 これにより、トリガーされたイベントが大量に発生するため、パフォーマンスの問題が発生しやすくなります。 つまり、window.resize
を使用すると、要素のサイズが実際に変更されたときだけでなく、すべてのビューポートサイズの変更が通知されるため、無駄になることがよくあります。
Resize Observer APIには、ウィンドウのサイズ変更イベントでは役に立たない別のユースケースもあります。要素がDOMに動的に追加または削除され、親要素のサイズに影響を与える場合です。 これは、最近のシングルページアプリでますます頻繁になっています。
このチュートリアルでは、ReactObserverの基本的な使用法について学習します。 また、独自のフロントエンドコードにReact Observerを実装し、ブラウザーのサポートをテストします。
前提条件
このチュートリアルを正常に完了するには、次のものが必要です。
- HTMLの理解。 HTMLシリーズでWebサイトを構築する方法は始めるのに最適な場所です。
- CSSの基本的な知識。 CSSシリーズを使用してWebサイトを構築する方法は、これを実現するのに役立ちます。
- JavaScript
for
およびforEach
ループの理解。 ループの詳細については、JavaScriptのForループ、For…Ofループ、For…Inループという記事をご覧ください。 この記事は、forEach
ループがどのように機能するかを完全に説明しています。 - JavaScriptでのDOM操作の理解。 このトピックについて詳しく知りたい場合は、 DOMの理解—ドキュメントオブジェクトモデルシリーズにアクセスしてください。
ステップ1—サイズ変更の基本的な使用法を理解する
Resize Observerの使用は、新しいResizeObserver
オブジェクトをインスタンス化し、監視されるエントリを受け取るコールバック関数を渡すことによって行われます。
const myObserver = new ResizeObserver(entries => {
});
コールバック関数内で、エントリを反復処理できます。 ResizeObserver
がインスタンス化されると、observe
関数がインスタンスで呼び出され、監視する要素が渡されます。
const someEl = document.querySelector('.some-element');
const someOtherEl = document.querySelector('.some-other-element');
myObserver.observe(someEl);
myObserver.observe(someOtherEl);
各エントリには、contentRect
およびtarget
プロパティを持つオブジェクトが割り当てられます。 target
はDOM要素自体であり、contentRect
は、幅、高さ、x、y、上、右、下、左のプロパティを持つオブジェクトです。
要素のgetBoundingClientRect
とは異なり、幅と高さのcontentRect
値にはパディング値が含まれていません。 contentRect.top
は要素の上部のパディングであり、contentRect.left
は要素の左側のパディングです。
たとえば、要素のサイズが変更されたときに観測された要素の幅と高さをログに記録する場合は、myObserver
という定数変数を作成し、新しいResizeObserver
をインスタンス化することから始めます。
const myObserver = new ResizeObserver(entries => {
});
コールバック関数内で、forEach
を使用してすべてのエントリを反復処理します。
const myObserver = new ResizeObserver(entries => {
entries.forEach(entry => {
});
});
forEach
ループ内で、console.log
は、それぞれentry.contentRect.width
とentry.contentRect.height
を使用した各エントリの幅と高さです。
const myObserver = new ResizeObserver(entries => {
entries.forEach(entry => {
console.log('width', entry.contentRect.width);
console.log('height', entry.contentRect.height);
});
});
myObserver
を使用するには、DOMセレクターを使用してsomeEl
という要素を作成します。 myObserver.observe
の引数としてsomeEl
を渡します。
const myObserver = new ResizeObserver(entries => {
entries.forEach(entry => {
console.log('width', entry.contentRect.width);
console.log('height', entry.contentRect.height);
});
});
const someEl = document.querySelector('.some-element');
myObserver.observe(someEl);
Resize Observerの使用方法を理解したら、実際のユースケースでResizeObserverを利用することに進むことができます。
ステップ2—サイズ変更オブザーバーの使用方法のデモンストレーション
以下は、ResizeObserverAPIの動作を確認するためのデモです。 ブラウザウィンドウのサイズを変更して試してみて、要素のサイズが実際に影響を受ける場合にのみ、グラデーションの角度とテキストの内容がどのように変化するかを確認してください。
Resize Observer APIを使用する前に、まずindex.html
ファイルを作成する必要があります。
- touch index.html
HTMLファイル内に、次のコードを追加します。
<div class="box">
<h3 class="info"></h3>
</div>
<div class="box small">
<h3 class="info"></h3>
</div>
また、HTMLにいくつかのスタイルを追加する必要があります。 styles.css
ファイルを作成し、そのファイルに次のCSSコードを追加します。
.box {
text-align: center;
height: 20vh;
border-radius: 8px;
box-shadow: 0 0 4px var(--subtle);
display: flex;
justify-content: center;
align-items: center;
}
.box h3 {
color: #fff;
margin: 0;
font-size: 5vmin;
text-shadow: 0 0 10px rgba(0,0,0,0.4);
}
.box.small {
max-width: 550px;
margin: 1rem auto;
}
.box
要素にグラデーションの背景を適用する必要がなかったことに注目してください。 サイズ変更オブザーバーは、ページが最初に読み込まれたときに1回呼び出され、次にグラデーションが適用されます。
それでは、JavaScriptコードに移りましょう。 外部JavaScriptファイルを作成することも、HTMLファイルに<script>
タグを追加することもできます。 まず、すべての.box
要素のDOMセレクターを作成します。
const boxes = document.querySelectorAll('.box');
次に、entries
というパラメーターを受け取るコールバック関数を使用して新しいResizeObserver
をインスタンス化します。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
});
entries
の各entry
を反復処理するfor...of
ループを作成します。 ループ内で、entry.target.querySelector('.info')
と等しく設定される定数変数infoEl
を作成します。 これは、.info
要素をtarget
として指します。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const infoEl = entry.target.querySelector('.info');
}
});
定数変数width
とheight
を作成し、それぞれentry.contentRect.width
とentry.contentRect.height
に設定します。 Math.floor
を両方に適用して、値を切り捨てます。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const infoEl = entry.target.querySelector('.info');
const width = Math.floor(entry.contentRect.width);
const height = Math.floor(entry.contentRect.height);
}
});
画面の幅に応じて変化する角度でグラデーションを作成するため、width / 360 * 100
と等しく設定されるangle
変数を作成します。 ここでも、Math.floor
を使用して、この値を切り捨てます。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const infoEl = entry.target.querySelector('.info');
const width = Math.floor(entry.contentRect.width);
const height = Math.floor(entry.contentRect.height);
const angle = Math.floor(width / 360 * 100);
}
});
線形グラデーションのコードを保持するgradient
という定数を作成します。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const infoEl = entry.target.querySelector('.info');
const width = Math.floor(entry.contentRect.width);
const height = Math.floor(entry.contentRect.height);
const angle = Math.floor(width / 360 * 100);
const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
}
});
このグラデーションを設定したら、entry.target.style.background
を使用して、ターゲットエントリの背景をgradient
に設定する必要があります。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const infoEl = entry.target.querySelector('.info');
const width = Math.floor(entry.contentRect.width);
const height = Math.floor(entry.contentRect.height);
const angle = Math.floor(width / 360 * 100);
const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
entry.target.style.background = gradient;
}
});
画面上のwidth
とheight
の値を変更として確認すると便利です。 infoEl
のinnerText
を取り、I'm ${width}px and ${height}px tall
に設定します。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const infoEl = entry.target.querySelector('.info');
const width = Math.floor(entry.contentRect.width);
const height = Math.floor(entry.contentRect.height);
const angle = Math.floor(width / 360 * 100);
const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
entry.target.style.background = gradient;
infoEl.innerText = `I'm ${width}px and ${height}px tall`;
}
});
ResizeObserver
のコールバックが完了しました。 これで、forEach
ループを使用して、myObserver
関数をboxes
に適用できます。
const boxes = document.querySelectorAll('.box');
const myObserver = new ResizeObserver(entries => {
for (let entry of entries) {
const infoEl = entry.target.querySelector('.info');
const width = Math.floor(entry.contentRect.width);
const height = Math.floor(entry.contentRect.height);
const angle = Math.floor(width / 360 * 100);
const gradient = `linear-gradient(${ angle }deg, rgba(0,143,104,1), rgba(250,224,66,1))`;
entry.target.style.background = gradient;
infoEl.innerText = `I'm ${width}px and ${height}px tall`;
}
});
boxes.forEach(box => {
myObserver.observe(box);
});
観察できる要素を繰り返し処理し、各要素でobserve
を呼び出す必要があることに注意してください。
これは、レスポンシブデザインにResizeObserverを使用する方法の実例です。 ただし、このようなJavaScript機能に対するブラウザのサポートに注意することが重要です。
ステップ3—ブラウザサポートの評価
Resize Observerのブラウザサポートは、現時点ではそれほど広範囲ではありません。 ありがたいことに、その間に使用できるポリフィルがあります。 ポリフィルは、 MutationObserverAPIに基づいています。
resizeobserverを使用できますか?にアクセスして、主要なブラウザー全体でこの機能のサポートを追跡できます。
結論
このチュートリアルでは、Reserve Observerで何ができるかを理解し、JavaScriptコードで使用して、ブラウザーのサポートをテストすることができました。
次のステップでは、ReactやVueなどのJavaScriptフレームワークを使用してレスポンシブデザインに取り組む方法を学ぶことに興味があるかもしれません。