concept

The IntersectionObserver interface (which is part of the IntersectionObserver API) provides developers with a way to asynchronously monitor the intersectionstate of a target element with its ancestors or viewports. Ancestor elements and viewports are called roots.

This is the official concept given by MDN, don’t worry about it, I just paste it to look professional…

The key here is to see if an element is visible in the window by monitoring the state of the target element crossing with its ancestor or window.

As you can see, crossing means that the current element is visible in the window.

API

var io = new IntersectionObserver(callback, options)
Copy the code

It’s a simple constructor.

The above code returns an instance of IntersectionObserver, callback is the callback function when the visibility of the element changes, and Options are some configuration items (optional).

We use the returned instance to do some things.

io.observe(document.querySelector('img')) to start observing, accept a DOM node object io.unobserve(element) to stop observing accept an element io.disconnect() to close the observerCopy the code

options

root

The root element for viewing, which is the browser viewport by default, can also be specified as a specific element, which must be a child of the specified element

threshold

An array that specifies the crossover ratio and determines when to trigger the callback function. The default is [0].

const options = { root: null, threshold: [0, 0.5, 1]} var IO = new IntersectionObserver(callback, options) IO. Observe (document.querySelector('img'))
Copy the code

In the code above, we specified a crossover ratio of 0,0.5, 1, and the callback will be triggered when the elements img0, 50%, and 100% are observed

rootMargin

To increase or decrease the size of the window, use the CSS definition method with the top, right, bottom and left values at 10px, 10px, 30px and 20px

const options = {
	root: document.querySelector('.box'),
	threshold: [0, 0.5, 1],
	rootMargin: '30px 100px 20px'
}
Copy the code

To make it easier to understand, I drew a picture like this

First of all, what is the blue line? It is the root element we defined. We added the rootMargin property to make the window larger. The dashed line is the window now, so the element is now inside the window.

Thus, the root element is an absolute window only when rootMargin is empty.

Having said simple options, let’s look at callback.

callback

As mentioned above, the callback function is triggered when the visibility of the element changes.

The callback function fires twice, both when the element enters the window (when it becomes visible) and when it leaves the window (when it becomes invisible)

var io = new IntersectionObserver((entries) = >{
	console.log(entries)
})

io.observe($0)
Copy the code

For the above code, please debug it in the Chrome console, where I used $0 to select the node where I last reviewed the element’s selection

The result is as follows

We can see a entries callback function parameters, it is a IntersectionObserverEntry array of objects, and then we focused on the IntersectionObserverEntry object

IntersectionObserverEntry

IntersectionObserverEntry observation elements of information, there are seven attributes.

BoundingClientRect Specifies the rectangle information for the target element

IntersectionRatio intersection area and the proportion of the target element values intersectionRect/boundingClientRect invisible when less than or equal to 0

The intersectionRect target element and the intersecting rectangle information of the window (root) can be called the intersection area

Whether the isIntersecting target element is currently visible Boolean is true if it is visible

RootBounds rectangle of the root element, which does not specify that the root element is the rectangle of the current window

Target Specifies the target element to view

Time returns a timestamp that records the time from IntersectionObserver to the time when the IntersectionObserver is triggered

The relationship of the above rectangles is as follows

👇 highlight

IntersectionRatio and isIntersecting are used to judge whether elements are visible.

Lazy loading

Ok, we have a general idea of what IntersectionObserver is based on the above concepts. Then we can use it to write some code. What should we write? Yes, lazy loading.

Lazy loading via IntersectionObserver is much easier. We only need to set a callback to determine whether the current element is visible and then perform the rendering operation without worrying about internal calculation.

The main code is as follows

const io = new IntersectionObserver((a)= >{ // Instantiation defaults to the current window
	
})  

let ings = document.querySelectorAll('[data-src]') // Set the real URL of the image to data-src instead of SRC when the SRC attribute is visible as a placeholder element

function callback(entries){  
	entries.forEach((item) = > { // Iterate through the entries array
		if(item.isIntersecting){ // The current element is visible
			item.target.src = item.target.dataset.src  / / replace the SRC
			io.unobserve(item.target)  // Stop observing the current element to avoid calling the callback function again when it is not visible
		}	
	})
}

imgs.forEach((item) = >{  // IO. Observe accepts a DOM element and adds multiple listeners using forEach
	io.observe(item)
})
	
Copy the code

I want to record a GIF, but I can’t upload it by Recordlt, if anyone has a good GIF recording software please recommend it.

Well, here you are 🌹

For the full code, please go to github 😜

⚠ ️ note

At present, IntersectionObserver is an experimental function, so please use it appropriately.