 朋友们,美好的一天!
朋友们,美好的一天!总览
Intersection Observer API(IOA)允许应用程序异步观察元素(目标)与其父元素(根)或视口(视口)的交集。换句话说,每次目标元素与根或视口相交时,此API都会提供对特定函数的调用。使用示例:- 延迟或延迟加载图像
- 无休止的页面滚动
- 接收有关广告可见度的信息,以计算印象费用
- 在用户的视野中启动过程或动画
要开始使用IOA,您需要使用构造函数来创建带有两个参数的观察者对象-回调函数和设置:
let options = {
    root: document.querySelector('.scroll-list'),
    rootMargin: '5px',
    threshold: 0.5
}
let callback = function(entries, observer){
    ...
}
let observer = new IntersectionObserver(callback, options)
设定:- root-充当目标视口的元素(目标元素的祖先,视口为null)
- rootMargin-根周围的边距(CSS中的边距,默认情况下所有边距均为0)
- 阈值-一个数字或数字数组,指示目标和根的交点的可接受百分比
接下来,创建目标元素,观察者将对其进行观察:let target = document.querySelector('.list-item')
observer.observe(target)
回调调用返回一个对象,该对象包含目标元素发生的更改的记录:let callback = (entries, observer) => {
    entries.forEach(entry => {
        
        
        
        
        
        
        
        
    })
}
该网络充满了有关理论的信息,但是有关使用IOA的实践的材料很多。我决定填补这一空白。例子
延迟(延迟)图像加载
任务:在用户滚动页面时上传(显示)图像。编码:
window.onload = () => {
    
    const options = {
        
        root: null,
        
        rootMargin: '0px',
        
        threshold: 0.5
    }
    
    const observer = new IntersectionObserver((entries, observer) => {
        
        entries.forEach(entry => {
            
            if (entry.isIntersecting) {
                const lazyImg = entry.target
                
                console.log(lazyImg)
                
                lazyImg.style.background = 'deepskyblue'
                
                observer.unobserve(lazyImg)
            }
        })
    }, options)
    
    const arr = document.querySelectorAll('img')
    arr.forEach(i => {
        observer.observe(i)
    })
}
结果: 视口外的容器的背景为白色。
视口外的容器的背景为白色。 当您跨过查看区域一半时,背景变为天蓝色。→ Codepen→  Github
当您跨过查看区域一半时,背景变为天蓝色。→ Codepen→  Github图像替换
任务:当用户滚动页面时,将占位符图像更改为原始图像。编码:window.onload = () => {
    const observer = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                console.log(entry)
                
                entry.target.src = entry.target.dataset.src
                observer.unobserve(entry.target)
            }
        })
    }, { threshold: 0.5 })
    document.querySelectorAll('img').forEach(img => observer.observe(img))
}
结果: 第一张图像已上传,因为它在查看区域中。第二个是占位符。
第一张图像已上传,因为它在查看区域中。第二个是占位符。 当您进一步滚动时,占位符将替换为原始图像。→ Codepen→  Github
当您进一步滚动时,占位符将替换为原始图像。→ Codepen→  Github更改容器背景
任务:当用户在那里滚动页面并返回时,更改容器的背景。编码:window.addEventListener('load', event => {
    let box = document.querySelector('div')
    
    let prevRatio = 0.0
    let observer = new IntersectionObserver((entries, observer) => {
        entries.forEach(entry => {
            let curRatio = entry.intersectionRatio
            
            
            
           
            curRatio > prevRatio ? entry.target.style.background = `rgba(40,40,190,${curRatio})` : entry.target.style.background = `rgba(190,40,40,${curRatio})`
            prevRatio = curRatio
        })
    }, {
        threshold: buildThresholdList()
    })
    observer.observe(box)
    
    
    
    function buildThresholdList() {
        let thresholds = []
        let steps = 20
        for (let i = 1.0; i <= steps; i++) {
            let ratio = i / steps
            thresholds.push(ratio)
        }
        return thresholds
    }
})
结果: 容器的背景从
容器的背景从 浅蓝色...
浅蓝色... 变为蓝色... 变为浅红色。→ Codepen→  Github
变为蓝色... 变为浅红色。→ Codepen→  Github处理视频
任务:暂停正在运行的视频,然后根据落入查看区域的视频重新开始播放。编码:window.onload = () => {
    let video = document.querySelector('video')
    let observer = new IntersectionObserver(() => {
        
        if (!video.paused) {
            
            video.pause()
        
        } else if(video.currentTime != 0) {
            
            video.play()
        }
    }, { threshold: 0.4 })
    observer.observe(video)
}
结果: 视频在观看区域中时,将播放。
视频在观看区域中时,将播放。 一旦视频超出观看区域40%以上,其播放就会暂停。如果您查看的观看区域>视频的40%,将继续播放。→ Codepen→  Github
一旦视频超出观看区域40%以上,其播放就会暂停。如果您查看的观看区域>视频的40%,将继续播放。→ Codepen→  Github页面浏览进度
任务:在用户滚动页面时显示查看页面的进度。编码:
let p = document.querySelector('p')
let n = 0
let observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if(entry.isIntersecting){
            
            
            
            p.textContent = `${n++} div viewed`
            observer.unobserve(entry.target)
        }
    })
}, {threshold: 0.9})
document.querySelectorAll('div').forEach(div => observer.observe(div))
结果:该 页面刚刚加载,因此我们尚未查看任何容器。
页面刚刚加载,因此我们尚未查看任何容器。 到达页面末尾时,该段落显示有关查看4格的信息。→ Codepen→  Github
到达页面末尾时,该段落显示有关查看4格的信息。→ Codepen→  Github无限滚动
任务:实现无尽的清单。编码:let ul = document.querySelector('ul')
let n = 1
function createLi(){
    li = document.createElement('li')
    li.innerHTML = `${++n} item`
    ul.append(li)
}
let observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            createLi()
        }
        observer.unobserve(entry.target)
        observer.observe(document.querySelector('li:last-child'))
    })
}, {
    threshold: 1
})
observer.observe(document.querySelector('li'))
结果: 我们有12个列表项。最后一项在视口之外。
我们有12个列表项。最后一项在视口之外。 当您尝试到达最后一个元素时,将创建一个对用户隐藏的新(最后)元素。等等到无穷大。→ Codepen→  Github
当您尝试到达最后一个元素时,将创建一个对用户隐藏的新(最后)元素。等等到无穷大。→ Codepen→  Github调整父母大小时调整孩子大小
任务:建立一个元素的大小对另一个元素的依赖性。编码:
let info = document.querySelector('.info')
let parent = document.querySelector('.parent')
let child = document.querySelector('.child')
child.style.width = parent.offsetWidth - 50 + 'px'
info.textContent = `child width: ${child.offsetWidth}px`
let options = {
    
    root: parent,
    threshold: 1
}
let observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        
        if ((entry.target.parentElement.offsetWidth - entry.target.offsetWidth) < 50) {
            
            entry.target.style.width = entry.target.offsetWidth - 50 + 'px'
        }
    })
}, options)
observer.observe(child)
window.addEventListener('resize', () => {
    info.textContent = `child width: ${child.offsetWidth}px`
    if ((parent.offsetWidth - child.offsetWidth) > 51) {
        child.style.width = child.offsetWidth + 50 + 'px'
    }
})
结果: 初始状态。
初始状态。 当减小父元素的宽度时,子元素的宽度减小。同时,它们之间的距离几乎总是等于50px(“几乎”是由于采用了反向机制)。→ Codepen→  Github
当减小父元素的宽度时,子元素的宽度减小。同时,它们之间的距离几乎总是等于50px(“几乎”是由于采用了反向机制)。→ Codepen→  Github处理动画
任务:在可见时为对象设置动画。编码:
let observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        entry.isIntersecting ? entry.target.classList.replace('to-left', 'to-right') : entry.target.classList.replace('to-right', 'to-left')
    })
}, {
    threshold: .5
})
observer.observe(document.querySelector('img'))
结果: 我们看到了Bart头部的一部分。巴特按下到查看区域的左侧。
我们看到了Bart头部的一部分。巴特按下到查看区域的左侧。 如果超过50%的Bart落入观看区域,他将移至中间。当超过50%的Bart离开查看区域时,它将返回其初始位置。→ Codepen→  Github谢谢您的关注。
如果超过50%的Bart落入观看区域,他将移至中间。当超过50%的Bart离开查看区域时,它将返回其初始位置。→ Codepen→  Github谢谢您的关注。