ResizeObserver
ResizeObserver 介面報告 Element 內容框或邊框框尺寸的更改,或 SVGElement 的邊界框的更改。
注意:內容框是可以放置內容的框,即邊框框減去內邊距和邊框寬度。邊框框包含內容、內邊距和邊框。請參閱 盒模型 以獲得進一步解釋。
建構函式
ResizeObserver()-
建立並返回一個新的
ResizeObserver物件。
例項屬性
無。
例項方法
ResizeObserver.disconnect()-
取消觀察特定觀察器所有被觀察的
Element目標。 ResizeObserver.observe()-
開始觀察指定的
Element。 ResizeObserver.unobserve()-
停止觀察指定的
Element。
示例
在 resize-observer-text.html (檢視原始碼) 示例中,我們使用 resize observer 在滑塊值改變導致包含的 <div> 寬度改變時,更改標題和段落的 font-size。這表明您可以響應元素大小的變化,即使這些變化與視口無關。
我們還提供了一個複選框來開啟和關閉觀察器。如果關閉,文字將不會響應 <div> 寬度變化而改變。
JavaScript 程式碼如下
const h1Elem = document.querySelector("h1");
const pElem = document.querySelector("p");
const divElem = document.querySelector("body > div");
const slider = document.querySelector('input[type="range"]');
const checkbox = document.querySelector('input[type="checkbox"]');
divElem.style.width = "600px";
slider.addEventListener("input", () => {
divElem.style.width = `${slider.value}px`;
});
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
if (entry.contentBoxSize) {
const contentBoxSize = entry.contentBoxSize[0];
h1Elem.style.fontSize = `${Math.max(
1.5,
contentBoxSize.inlineSize / 200,
)}rem`;
pElem.style.fontSize = `${Math.max(
1,
contentBoxSize.inlineSize / 600,
)}rem`;
} else {
h1Elem.style.fontSize = `${Math.max(
1.5,
entry.contentRect.width / 200,
)}rem`;
pElem.style.fontSize = `${Math.max(1, entry.contentRect.width / 600)}rem`;
}
}
console.log("Size changed");
});
resizeObserver.observe(divElem);
checkbox.addEventListener("change", () => {
if (checkbox.checked) {
resizeObserver.observe(divElem);
} else {
resizeObserver.unobserve(divElem);
}
});
觀察錯誤
遵循規範的實現會在繪製前(即在幀顯示給使用者之前)呼叫 resize 事件。如果有任何 resize 事件,將重新評估樣式和佈局 — 這反過來可能會觸發更多 resize 事件。由迴圈依賴引起的無限迴圈透過在每次迭代中僅處理 DOM 中更深的元素來解決。不滿足此條件的 resize 事件將推遲到下一個繪製,並在 Window 物件上觸發一個錯誤事件,帶有明確定義的字串訊息
ResizeObserver loop completed with undelivered notifications.
請注意,這僅能防止使用者代理鎖定,而不能防止無限迴圈本身。例如,以下程式碼將導致 divElem 的寬度無限增長,並在每個幀中在控制檯中重複出現上述錯誤訊息
const divElem = document.querySelector("body > div");
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
entry.target.style.width = `${entry.contentBoxSize[0].inlineSize + 10}px`;
}
});
resizeObserver.observe(divElem);
window.addEventListener("error", (e) => {
console.error(e.message);
});
只要錯誤事件不無限觸發,resize observer 就會穩定下來併產生一個穩定、可能正確的佈局。但是,訪問者可能會看到短暫的損壞佈局,因為本應在一個幀中發生的一系列更改卻發生在多個幀中。
如果您想防止這些錯誤,解決方案取決於您的預期效果。如果您確實打算實現無限迴圈,只需將 ResizeObserver 回撥中的重置程式碼推遲到瀏覽器重繪之後即可。您可以將其放入 requestAnimationFrame 回撥中。
const divElem = document.querySelector("body > div");
const resizeObserver = new ResizeObserver((entries) => {
requestAnimationFrame(() => {
for (const entry of entries) {
entry.target.style.width = `${entry.contentBoxSize[0].inlineSize + 10}px`;
}
});
});
resizeObserver.observe(divElem);
window.addEventListener("error", (e) => {
console.error(e.message);
});
如果您無意實現無限迴圈,則應確保您的重置程式碼不會觸發 resize observer 回撥。有多種方法可以實現這一點,例如設定一個“預期大小”,如果大小已經達到該值則不進行重置。
const divElem = document.querySelector("body > div");
const expectedSizes = new WeakMap();
const resizeObserver = new ResizeObserver((entries) => {
requestAnimationFrame(() => {
for (const entry of entries) {
const expectedSize = expectedSizes.get(entry.target);
if (entry.contentBoxSize[0].inlineSize === expectedSize) {
continue;
}
const newSize = entry.contentBoxSize[0].inlineSize + 10;
entry.target.style.width = `${newSize}px`;
expectedSizes.set(entry.target, newSize);
}
});
});
resizeObserver.observe(divElem);
window.addEventListener("error", (e) => {
console.error(e.message);
});
規範
| 規範 |
|---|
| Resize Observer(調整大小觀察器) # resize-observer-interface |
瀏覽器相容性
載入中…
另見
- 學習:盒模型
PerformanceObserverIntersectionObserver(屬於 Intersection Observer API)- 即將推出的 容器查詢 可能是實現響應式設計的一個可行替代方案。