Detailed explanation of Intersection Observer API (cross observer)

1. Introduction

Intersection Observer APIProvides a method to monitor whether the target element is displayed to the viewport ( viewport) . Common demand scenarios:

  • Lazy loading of images
  • scroll animation

For the above requirements, in the past , events were generally monitored and methods were used to obtain the location information of the target elementscrollgetBoundingClientRect() . Due to monitoring scrollevents, reflow is continuously triggered , which has a certain impact on performance. However, it can be solved through function throttling , but getBoundingClientRect()the impact of this method on performance cannot be effectively optimized.

! ! ! Therefore, in order to solve the above problems, the browser introduced it IntersectionObserver API. Since the method is asynchronous, it does not affect the execution efficiency of the main thread.

2. Compatibility

It is compatible with the mainstream browsers on the market. Generally speaking, it is optimistic. However, for the sake of the rigor of the code, let’s make a simple judgment:

if (window?.IntersectionObserver) {
    
    
	let io = new IntersectionObserver(callback, options)
	io.observe(targetElement)
}

Insert image description here

3. Built-in methods/properties

let io = new IntersectionObserver(entries => {
    
    
	// IntersectionObserverEntry 作为一个参数返回
	console.log(entries)
}, {
    
     root: null, rootMargin: '0px 0px', threshold: [0.5, 1] })

// 开始监听
io.observe(targetElement)
// 停止监听
io.unobserve(targetElement)
// 结束监听器
io.disconnect()

As we can see above, IntersectionObserverit receives a callback function and an object optionsas parameters.

IntersectionObserverEntryentriesThe instance is passed to the callback function as a parameter, providing information about the element at that time.


See entrieswhat properties it has:

Insert image description here

Attributes effect
boundingClientRect Information about the rectangular area of ​​the target element
intersectionRatio The visible proportion of the target element, that is, the proportion of , is 1 when it is completely visible, and is less than or equal to 0 when it intersectionRectis boundingClientRectcompletely invisible.
intersectionRect Information about the intersection area between the target element and the viewport (or root element)
isIntersecting Whether the target target element has been converted to the intersected state ( true) or to the disjoint state ( false)
rootBounds Information about the rectangular area of ​​the root element, getBoundingClientRect()the return value of the method, if there is no root element (that is, scrolling directly relative to the viewport), it is returnednull
target The target element being observed is a DOMnode object
time The time when the visibility changed, which is a high-precision timestamp in milliseconds

APIProvided methods/properties:

methods/properties effect
root Root element, default viewport ( viewport)
rootMargin Offset relative to the root element, default value is "0px 0px"
threshold Gate value that triggers the callback function, in ascending order, default 0, optional: [0, 0.25, 0.5, 0.75, 1]
observe(targetElement) Start monitoring, must transmit targetElement, can observe multiple nodes at the same time
unobserve(targetElement) Stop monitoring, must transmittargetElement
takeRecords() IntersectionObserverEntryReturns an array of objects for all listening targets and stops listening on them
disconnect() Stop the listener from working

4. Use

Let’s write a scrolling update element content/style function here:
Insert image description here

HTML:

<div class="container">
  <div class="item" data-id="1">元素1:不可见</div>
  <div class="item" data-id="2">元素2:不可见</div>
  <div class="item" data-id="3">元素3:不可见</div>
  <div class="item" data-id="4">元素4:不可见</div>
  <div class="item" data-id="5">元素5:不可见</div>
</div>

JS:Modify the text/background color when the target element is fully exposed/not fully exposed

<script>
  if (window?.IntersectionObserver) {
    
    
    let items = [...document.getElementsByClassName('item')] // 解析为真数组,也可用 Array.prototype.slice.call()

    let io = new IntersectionObserver(entries => {
    
    
      entries.forEach(item => {
    
    
        // intersectionRatio === 1说明该元素完全暴露出来
        if (item.intersectionRatio === 1) {
    
    
          item.target.style.backgroundColor = 'deeppink'
          item.target.innerHTML = `元素${
      
      item.target.getAttribute('data-id')}:完全可见`
        } else {
    
    
          item.target.style.backgroundColor = 'deepskyblue'
          item.target.innerHTML = `元素${
      
      item.target.getAttribute('data-id')}:不可见`
        }
      })
    }, {
    
    
      root: null,
      rootMargin: '0px 0px',
      threshold: 1 // 阀值设为1,当只有比例达到1时才触发回调函数
    })

    items.forEach(item => io.observe(item))
  }
</script>

5. Related links

Guess you like

Origin blog.csdn.net/Vue2018/article/details/128151898