Selamat siang teman!Gambaran
Intersection Observer API (IOA) memungkinkan aplikasi untuk secara asinkron memantau persimpangan elemen (target) dengan induknya (root) atau viewport (viewport). Dengan kata lain, API ini menyediakan panggilan ke fungsi tertentu setiap kali elemen target bersinggungan dengan root atau viewport.Contoh penggunaan:- Pemuatan gambar yang malas atau malas
- Pengguliran halaman tanpa akhir
- menerima informasi tentang visibilitas iklan untuk tujuan menghitung biaya tayangan
- memulai proses atau animasi di bidang penglihatan pengguna
Untuk mulai bekerja dengan IOA, Anda perlu menggunakan konstruktor untuk membuat objek pengamat dengan dua parameter - fungsi dan pengaturan callback:
let options = {
root: document.querySelector('.scroll-list'),
rootMargin: '5px',
threshold: 0.5
}
let callback = function(entries, observer){
...
}
let observer = new IntersectionObserver(callback, options)
Pengaturan:- root - elemen yang bertindak sebagai viewport untuk target (leluhur dari elemen target atau null untuk viewport)
- rootMargin - margin di sekitar root (margin di CSS, secara default semua margin adalah 0)
- threshold - angka atau array angka yang menunjukkan persentase persimpangan target dan root yang dapat diterima
Berikutnya, elemen target dibuat, yang ditonton pengamat:let target = document.querySelector('.list-item')
observer.observe(target)
Panggilan balik mengembalikan objek yang berisi catatan perubahan yang telah terjadi dengan elemen target:let callback = (entries, observer) => {
entries.forEach(entry => {
})
}
Jaringan ini penuh dengan informasi tentang teori, tetapi sedikit materi tentang praktik menggunakan IOA. Saya memutuskan untuk mengisi sedikit celah ini.Contohnya
Pemuatan gambar yang malas (tertunda)
Tugas: mengunggah (menampilkan) gambar saat pengguna menggulir halaman.Kode:
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)
})
}
Hasil:
Latar belakang wadah di luar viewport berwarna putih.
Saat Anda melintasi area tampilan setengah, latar berubah menjadi biru langit.→ Codepen→ GithubPenggantian Gambar
Tugas: mengubah gambar placeholder ke aslinya ketika pengguna menggulir halaman.Kode: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))
}
Hasil:
Gambar pertama diunggah karena berada di area tampilan. Yang kedua adalah placeholder.
Saat Anda menggulir lebih jauh, placeholder diganti dengan gambar asli.→ Codepen→ GithubUbah latar belakang wadah
Tugas: untuk mengubah latar belakang wadah saat pengguna menggulir halaman di sana dan kembali.Kode: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
}
})
Hasil:
Latar belakang wadah berubah dari biru
muda ...
menjadi biru ... menjadi merah muda.→ Codepen→ GithubBekerja dengan video
Tugas: Jeda video yang sedang diputar dan mulai lagi tergantung pada video yang jatuh ke area tampilan.Kode: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)
}
Hasil:
Saat video berada di area tontonan, video diputar.
Segera setelah video melampaui area tontonan lebih dari 40%, pemutarannya jeda. Jika Anda menekan area tampilan> 40% dari video, pemutarannya dilanjutkan.→ Codepen→ GithubKemajuan Tampilan Halaman
Tugas: menampilkan kemajuan dalam melihat halaman saat pengguna menggulir halaman.Kode:
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))
Hasil:
Halaman baru saja dimuat, jadi kami belum melihat wadah apa pun.
Ketika akhir halaman tercapai, paragraf menampilkan informasi tentang melihat 4 div.→ Codepen→ GithubPengguliran tanpa akhir
Tugas: mengimplementasikan daftar tanpa akhir.Kode: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'))
Hasil:
Kami memiliki 12 item daftar. Item terakhir berada di luar viewport.
Saat Anda mencoba untuk sampai ke elemen terakhir, elemen baru (terakhir) dibuat yang disembunyikan dari pengguna. Dan seterusnya hingga tak terbatas.→ Codepen→ GithubMengubah ukuran anak ketika mengubah ukuran orang tua
Tugas: menetapkan ketergantungan ukuran satu elemen pada elemen lainnya.Kode:
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'
}
})
Hasil:
Status awal.
Saat mengurangi lebar elemen induk, lebar elemen turunan berkurang. Pada saat yang sama, jarak di antara mereka hampir selalu sama dengan 50px ("hampir" disebabkan oleh implementasi mekanisme terbalik).→ Codepen→ GithubBekerja dengan animasi
Tugas: menghidupkan objek ketika terlihat.Kode:
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'))
Hasil:
Kami melihat bagian kepala Bart. Bart menekan ke sisi kiri area tampilan.
Jika lebih dari 50% Bart jatuh ke area tampilan, ia bergerak ke tengah. Ketika lebih dari 50% Bart meninggalkan area tampilan, ia kembali ke posisi semula.→ Codepen→ GithubTerima kasih atas perhatian Anda.