Obserwowanie zmian rozmiaru elementów z Resize Observer API

Od niedawna przeglądarki oparte na Chromium, Firefox oraz Safari zaczęły wspierać API, które umożliwia w wydajny sposób śledzić zmiany wielkości dowolnego elementu na stronie. Resize Observer, bo o nim tu mowa, udostępnia prostą specyfikację, niemal bliźniaczo podobną do innych obserwatorów, takich jak Intersection Observer, Mutation Observer czy Performance Observer. Spójrzmy, w jaki sposób możemy zacząć pracować z tą bardzo przydatną klasą.
Data dodania:
Obserwowanie zmian rozmiaru elementów z Resize Observer API

Spis treści

Specyfikacja Resize Observer API jest wciąż we wczesnym etapie prac (obecnie w fazie Editor’s Draft). Mimo tego aktualna wersja dociera do około 83.7% użytkowników. Bez przeszkód można korzystać z dobrodziejstw tego API w =< Chrome 64, =< Firefox 69 czy =< Safari 13.1. Aktualna lista wsparcia znajduje się na caniuse.

Jeżeli chcesz wspierać większą ilość wersji przeglądarek, możesz skorzystać z polyfilla znajdującego się na GitHubie. Dzięki niemu korzystanie z Resize Observer będzie możliwe nawet na Internet Explorer 9.

Zanim zaczniemy

W tym artykule rzucam wyłącznie światło na tą specyfikację, starając się przy tym zachęcić Cię do zagłębienia się w to API. Przez to nie poruszam wszystkich możliwych zachowań, właściwości oraz metod. Chcąc dowiedzieć się więcej, odsyłam do świetnej dokumentacji znajdującej się na Mozilla Developer Network.

Stwórzmy pierwszego observera

Skoro mamy pogląd na to, czym jest Resize Observer i czy możemy z niego korzystać, zacznijmy od krótkiego omówienia konstruktora. Tworząc nową instancję klasy _ResizeObserver_, przekazujemy w pierwszym (i jedynym) argumencie callback, który będzie wywoływany za każdym razem, gdy obserwowane elementy zmienią swoje rozmiary. „` javascript const callback = (entries, observer) => { for (let entry of entries) { /* code */ } }; const ro = new ResizeObserver(callback); ro.observe(element); „` Metoda callback przyjmie dwa parametry – `entries`, który zawiera tablicę wszystkich obserwowanych elementów oraz `observer`, będącym referencją do utworzonej instancji observera.

Box model

Domyślnie callback wywoływany jest wtedy, gdy _content box_ elementu zostanie zmodyfikowany (lub _bounding box_, jeżeli rozmiar zmienia element SVG). Zachowanie to można zmodyfikować, podając w drugim argumencie metody _observe_ obiekt z konfiguracją, gdzie (podając klucz _box_) mówimy, dla którego _box model_ respektowane będą zmiany wielkości elementu (domyślną wartością jest _content box_). „` javascript ro.observe(element, { box: 'border-box’, // border-box or content-box }); „`

Po więcej informacji na temat box model odsyłam do dokumentacji w serwisie MDN.

Praktyczny przykład

Przygotowałem prosty przykład, żeby pokazać działania klasy _Resize Observer_. Stworzyłem prosty kontener z tekstem oraz obrazkiem. Dodatkowo dopisałem funkcjonalność, która będzie zmniejszała szerokość kontenera, żeby zaprezentować działanie bez skalowania okna. Przykład działania Resize Observer Jak można zauważyć – informacje na temat rozmiarów elementów aktualizują się za każdym razem, gdy element zmieni swój rozmiar. Każda zmiana wykonywana na elementach DOM jest bardzo wydajna, ponieważ _Resize Observer_ wywołuje wszystkie callbacki bezpośrednio po etapie _layout_, ale jeszcze przed _paint_. Znaczy to tyle, że nasze zmiany unieważnią tylko etap _layout_, co jest zdecydowanie mniej kosztowne dla przeglądarki, gdyż zmiana nie wymusza ponownego wyrenderowania strony. Lista kroków przy renderowaniu pojedyńczej klatki w przeglądarce Rozmiary pobierane są z obiektu `contentRect`, który zawiera właściwości interfejsu DOMRectReadOnly. Obiekt ten zawiera właściwości tylko do odczytu i aktualne rozmiary obserwowanego elementu, odpowiadające _content box_ elementu. Trzeba wziąć pod uwagę, że ta właściwość jest pozostałością po wcześniejszej implementacji i może w przyszłości zostać potraktowana jako przestarzała. Obecnie przyjęto w specyfikacji, że aktualne rozmiary będą przechowywane w obiektach _borderBoxSize_ oraz _contentBoxSize_. Po więcej informacji odsyłam do strony na MDN.

∞ – nieskończone pętle

Zostało jeszcze pytanie: co, jeżeli w callbacku zmienimy rozmiar obserwowanego elementu? Odpowiedź jest prosta: NIC :), a to dlatego, że _Resize Observer_ jest zabezpieczone na taką ewentualność i unika nieskończonych pętli oraz cyklicznych zależności, które mogłyby z tego wyniknąć. Takie zmiany są wykonywane w następnej klatce. Natomiast istnieje wyjątek i obliczenia zostaną wykonane w tej samej klatce, jeżeli zmiana wielkości nastąpiła na elemencie, który znajduje się głębiej w drzewie DOM niż najpłytszy element, przetworzony w poprzednim callbacku.

Słowo na koniec

Mimo tego, że _Resize Observer API_ jest dosyć nową funkcjonalnością w naszych przeglądarkach, to warto już teraz się nią zainteresować. Wspomniany wcześniej polyfill pokryje wszystkie nowoczesne (i także te starsze ;)) przeglądarki, więc już od teraz można korzystać z tego API bez obaw.
Obserwowanie zmian rozmiaru elementów z Resize Observer API

Przemysław Tyczyński

Oceń nasz artykuł

Twoja opinia jest dla nas ważna

4.8/5 na podstawie 9 głosów

Chcesz otrzymać indywidualną wycenę naszych usług

Wypełnij i prześlij krótki brief. Wrócimy z wyceną najszybciej, jak to możliwe.