Reputation: 763
Why the ResizeObserver
class always execute the handler at the first observe()
?
Try execute the code below on Chrome' dev tool:
(new ResizeObserver(() => console.log('resize detected'))).observe($0)
You will see the log printed immediately after you apply it, even if you didn't do any size change.
I need the resize observer that only executes the handler on resize.
Is there any hack/options to tweak it?
let disableObserver = false;
const obs = new ResizeObserver(() => {
if (!disableObserver) {
console.log('resize detected');
}
});
// the hack below doesn't work:
disableObserver = true;
obs.observe(someElement);
disableObserver = false;
Upvotes: 6
Views: 5134
Reputation: 2244
I wrote Wrapper for build-in ResizeObserver which reacts only on sizeChanging and ignores hiding and displaying.
class ResizeObserverWrapper {
_lastWidth;
_lastHeight;
observe(htmlElement, onSizeChanged) {
new ResizeObserver(entries => {
if (entries != undefined && entries.length > 0) {
const newWidth = entries[0].target.clientWidth;
const newHeight = entries[0].target.clientHeight;
if (newWidth != undefined && newWidth > 0
&& newHeight != undefined && newHeight > 0
) {
let dimensionChanged = newWidth != this._lastWidth && this._lastWidth > 0
|| newHeight != this._lastHeight && this._lastHeight > 0 ;
this._lastHeight = newHeight;
this._lastWidth = newWidth;
if (dimensionChanged) {
onSizeChanged();
}
}
}
}).observe(htmlElement);
}
}
usage example:
new ResizeObserverWrapper().observe(yourRootElement.querySelector('.some-css-class'), () => console.log("It is resized"));
Upvotes: 1
Reputation: 2141
Tested in different browsers and the reported behaviour is consistent - observer callback is called when observer()
is called.
I've checked the specification, it says:
- Observation will fire when watched Element is inserted/removed from DOM.
- Observation will fire when watched Element display gets set to none.
- Observations do not fire for non-replaced inline Elements.
- Observations will not be triggered by CSS transforms.
- Observation will fire when observation starts if Element is being rendered, and Element’s size is not 0,0.
I guess initial call is because of Element being rendered.
Each element can be added to a Set to skip initial call. Something like this:
let entriesSeen = new Set(); // set of entries to skip initial resize call
const obs = new ResizeObserver((entries) => {
for (let entry of entries) {
if (!entriesSeen.has(entry.target)) {
// do nothing during initial call
// just mark element as seen
entriesSeen.add(entry.target);
} else {
console.log('resize detected');
console.log(entry.target);
}
}
});
obs.observe(someElement);
Upvotes: 7