IntersectionObserver API tutorial
When developing a web page, it is often necessary to know whether an element has entered the “viewport”, that is, whether the user can see it.
The green square in the picture above keeps scrolling, and its visibility will be indicated at the top.
The traditional method of implementation is to
scroll
call the target element (green square)
getBoundingClientRect()
method
after
listening to the
event
, get the coordinates corresponding to the upper left corner of the viewport, and then determine whether it is within the viewport.
The disadvantage of this method is that due to the
scroll
intensive occurrence of events, the amount of calculation is large, and it is easy to cause
performance problems
.
Currently there is a new IntersectionObserver API , which can automatically “observe” whether an element is visible or not. Chrome 51+ already supports it. Since the essence of visible is that the target element and the viewport produce an intersection area, this API is called “intersection observer”.
One, API
Its usage is very simple.
var io = new IntersectionObserver(callback, option);
In the above code, it
IntersectionObserver
is the constructor provided by the browser, which accepts two parameters:
callback
the callback function when the visibility changes, and
option
the configuration object (this parameter is optional).
The return value of the constructor is an observer instance.
The
observe
method of the
instance
can specify which DOM node to observe.
// 开始观察 io.observe(document.getElementById('example')); // 停止观察 io.unobserve(element); // 关闭观察器 io.disconnect();
In the above code,
observe
the parameter is a DOM node object.
If you want to observe multiple nodes, you must call this method multiple times.
io.observe(elementA); io.observe(elementB);
Two, callback parameters
When the visibility of the target element changes, the callback function of the observer is called
callback
.
callback
Usually it will be triggered twice.
Once the target element has just entered the viewport (begins visible), and the other time it has left the viewport completely (begins not visible).
var io = new IntersectionObserver( entries => { console.log(entries); } );
In the above code, the callback function is
written
in
arrow function
.
callback
The parameter (
entries
) of the
function
is an array, and each member is an
IntersectionObserverEntry
object.
For example, if the visibility of two observed objects changes at the same time, the
entries
array will have two members.
Three, IntersectionObserverEntry object
IntersectionObserverEntry
The object provides information about the target element, and there are six attributes in total.
{ time: 3893.92, rootBounds: ClientRect { bottom: 920, height: 1024, left: 0, right: 1024, top: 0, width: 920 }, boundingClientRect: ClientRect { // ... }, intersectionRect: ClientRect { // ... }, intersectionRatio: 0.54, target: element }
The meaning of each attribute is as follows.
time
: The time when the visibility changes, a high-precision timestamp, in millisecondstarget
: The target element to be observed is a DOM node objectrootBounds
: Information about the rectangular area of the root element,getBoundingClientRect()
the return value of the method, if there is no root element (that is, scroll directly relative to the viewport), then returnnull
boundingClientRect
: Information about the rectangular area of the target elementintersectionRect
: Information about the intersection area between the target element and the viewport (or root element)intersectionRatio
: The visible proportion of the target element, that isintersectionRect
,boundingClientRect
the proportion, when it is completely visible, and when it is1
completely invisible, it is less than or equal to0
In the above figure, the gray horizontal box represents the viewport, and the dark red area represents the four observed target elements.
They
intersectionRatio
have been noted in
their respective
figures.
I wrote a
Demo
, a demo
IntersectionObserverEntry
object.
Note that this Demo can only be run on Chrome 51+.
4. Example: lazy load
Sometimes, we hope that certain static resources (such as pictures) will only be loaded when the user scrolls down and enter the viewport, which can save bandwidth and improve web page performance. This is called “lazy loading”.
With the IntersectionObserver API, implementation is very easy.
function query(selector) { return Array.from(document.querySelectorAll(selector)); } var observer = new IntersectionObserver( function(changes) { changes.forEach(function(change) { var container = change.target; var content = container.querySelector('template').content; container.appendChild(content); observer.unobserve(container); }); } ); query('.lazy-loaded').forEach(function (item) { observer.observe(item); });
In the above code, only when the target area is visible, will the template content be inserted into the real DOM, which triggers the loading of static resources.
5. Example: Infinite scrolling
The implementation of infinite scroll is also very simple.
var intersectionObserver = new IntersectionObserver( function (entries) { // 如果不可见,就返回 if (entries[0].intersectionRatio <= 0) return; loadItems(10); console.log('Loaded new items'); }); // 开始观察 intersectionObserver.observe( document.querySelector('.scrollerFooter') );
For infinite scrolling, it is best to have a footer bar (also known as
sentinels
)
at the bottom of the page
.
Once the footer bar is visible, it means that the user has reached the bottom of the page, and new items are loaded and placed in front of the footer bar.
The advantage of this is that there is no need to call the
observe()
method again, and the existing ones
IntersectionObserver
can be kept in use.
Six, Option object
IntersectionObserver
The second parameter of the constructor is a configuration object.
It can set the following properties.
6.1 threshold attribute
threshold
The attribute determines when the callback function is triggered.
It is an array, each member is a threshold value, the default is
[0]
, that
is
, the
callback function is triggered when the
cross ratio (
intersectionRatio
) is reached
0
.
new IntersectionObserver( entries => {/* ... */}, { threshold: [0, 0.25, 0.5, 0.75, 1] } );
The user can customize this array.
For example,
[0, 0.25, 0.5, 0.75, 1]
it means that when the target element is 0%, 25%, 50%, 75%, 100% visible, the callback function will be triggered.
6.2 root attribute, rootMargin attribute
In many cases, the target element will not only scroll with the window, but also scroll inside the container (such as scrolling in the
iframe
window).
Scrolling in the container also affects the visibility of the target element, see the diagram at the beginning of this article.
The IntersectionObserver API supports scrolling within the container.
root
The attribute specifies the container node (that is, the root element) where the target element is located.
Note that the container element must be the ancestor node of the target element.
var opts = { root: document.querySelector('.container'), rootMargin: "500px 0px" }; var observer = new IntersectionObserver( callback, opts );
In the above code, in addition to
root
attributes, there are also
rootMargin
attributes.
The latter defines the root element
margin
and is used to expand or reduce the size of
rootBounds
the rectangle, thereby affecting
intersectionRect
the size of the intersection area.
It uses CSS definition methods, for example
10px 20px 30px 40px
, to represent the values of top, right, bottom, and left in the four directions.
After this setting, whether it is window scrolling or container scrolling, as long as the visibility of the target element changes, the observer will be triggered.
Seven, pay attention
The IntersectionObserver API is asynchronous and is not triggered synchronously with the scrolling of the target element.
The specification states that
IntersectionObserver
the implementation should be adopted
requestIdleCallback()
, that is, the observer will only be executed when the thread is idle.
This means that the priority of this observer is very low and will only be executed when other tasks are completed and the browser is free.
8. Reference link
(over)