Bonjour mes amis!Aperçu
L'API Intersection Observer (IOA) permet à une application d'observer de manière asynchrone l'intersection d'un élément (cible) avec son parent (racine) ou vue (vue). En d'autres termes, cette API fournit un appel à une fonction spécifique chaque fois que l'élément cible croise la racine ou la fenêtre.Exemples d'utilisation:- Chargement d'images paresseux ou paresseux
- défilement de page sans fin
- recevoir des informations sur la visibilité de la publicité dans le but de calculer le coût des impressions
- démarrer un processus ou une animation dans le champ de vision de l'utilisateur
Pour commencer à travailler avec IOA, vous devez utiliser le constructeur pour créer un objet observateur avec deux paramètres - une fonction de rappel et des paramètres:
let options = {
root: document.querySelector('.scroll-list'),
rootMargin: '5px',
threshold: 0.5
}
let callback = function(entries, observer){
...
}
let observer = new IntersectionObserver(callback, options)
Réglages:- root - un élément qui agit comme une fenêtre pour la cible (ancêtre de l'élément cible ou null pour la fenêtre)
- rootMargin - marges autour de root (marge en CSS, par défaut toutes les marges sont 0)
- seuil - un nombre ou un tableau de nombres indiquant le pourcentage acceptable d'intersection de la cible et de la racine
Ensuite, l'élément cible est créé, que l'observateur observe:let target = document.querySelector('.list-item')
observer.observe(target)
L'appel de rappel renvoie un objet contenant des enregistrements des modifications qui se sont produites avec l'élément cible:let callback = (entries, observer) => {
entries.forEach(entry => {
})
}
Le réseau regorge d'informations sur la théorie, mais pas mal de matériel sur la pratique de l'utilisation de l'AIO. J'ai décidé de combler un peu cette lacune.Exemples
Chargement d'image paresseux (retardé)
Tâche: télécharger (afficher) des images lorsque l'utilisateur fait défiler la page.Le code:
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)
})
}
Résultat: l'
arrière-plan du conteneur en dehors de la fenêtre est blanc.
Lorsque vous traversez la zone de visualisation de moitié, l'arrière-plan devient bleu ciel.→ Codepen→ GithubRemplacement d'image
Tâche: remplacez l'image d'espace réservé par l'original lorsque l'utilisateur fait défiler la page.Le code: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))
}
Résultat:
la première image est téléchargée car elle se trouve dans la zone de visualisation. Le second est l'espace réservé.
Lorsque vous faites défiler la page, l'espace réservé est remplacé par l'image d'origine.→ Codepen→ GithubChanger l'arrière-plan du conteneur
Tâche: changer l'arrière-plan du conteneur lorsque l'utilisateur fait défiler la page vers l'arrière et vers l'arrière.Le code: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
}
})
Résultat: l'
arrière-plan du conteneur passe du bleu clair ...
au bleu ...
au rouge clair.→ Codepen→ GithubTravailler avec la vidéo
Tâche: suspendez la vidéo en cours et redémarrez-la en fonction de la vidéo tombant dans la zone de visualisation.Le code: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)
}
Résultat:
lorsque la vidéo se trouve dans la zone de visualisation, elle est lue.
Dès que la vidéo dépasse de plus de 40% la zone de visualisation, sa lecture s'arrête. Si vous frappez la zone de visualisation> 40% de la vidéo, sa lecture reprend.→ Codepen→ GithubProgression de l'affichage de la page
Tâche: affichez la progression de l'affichage de la page lorsque l'utilisateur fait défiler la page.Le code:
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))
Résultat: la
page vient d'être chargée, nous n'avons donc pas encore regardé de conteneurs.
Lorsque la fin de la page est atteinte, le paragraphe affiche des informations sur l'affichage de 4 divisions.→ Codepen→ GithubDéfilement sans fin
Tâche: implémenter une liste sans fin.Le code: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'))
Résultat:
nous avons 12 éléments de liste. Le dernier élément est en dehors de la fenêtre.
Lorsque vous essayez d'accéder au dernier élément, un nouvel (dernier) élément est créé qui est caché à l'utilisateur. Et ainsi de suite à l'infini.→ Codepen→ GithubRedimensionner un enfant lors du redimensionnement d'un parent
Tâche: établir la dépendance de la taille d'un élément sur un autre.Le code:
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'
}
})
Résultat:
état initial.
Lors de la réduction de la largeur de l'élément parent, la largeur de l'élément enfant diminue. Dans le même temps, la distance entre eux est presque toujours égale à 50 px («presque» est due à la mise en œuvre du mécanisme inverse).→ Codepen→ GithubTravailler avec l'animation
Tâche: animer un objet lorsqu'il est visible.Le code:
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'))
Résultat:
on voit une partie de la tête de Bart. Bart appuya sur le côté gauche de la zone d'observation.
Si plus de 50% de Bart tombe dans la zone d'observation, il se déplace vers le milieu. Lorsque plus de 50% de Bart quitte la zone de visualisation, il revient à sa position initiale.→ Codepen→ GithubMerci de votre attention.