يوم جيد يا اصدقاء!نظرة عامة
تسمح واجهة Intersection Observer API (IOA) للتطبيق بمراقبة تقاطع عنصر (هدف) بشكل غير متزامن مع أصله (الجذر) أو إطار العرض (إطار العرض). بمعنى آخر ، توفر واجهة برمجة التطبيقات هذه استدعاء لوظيفة محددة في كل مرة يتقاطع فيها العنصر الهدف مع الجذر أو إطار العرض.أمثلة على استخدام:- كسول أو تحميل كسول من الصور
- التمرير صفحة لا نهاية لها
- تلقي معلومات حول وضوح الإعلان لغرض حساب تكلفة الظهور
- بدء عملية أو رسم متحرك في مجال رؤية المستخدم
لبدء العمل مع IOA ، تحتاج إلى استخدام المُنشئ لإنشاء كائن مراقب بمعلمتين - وظيفة رد الاتصال والإعدادات:
let options = {
root: document.querySelector('.scroll-list'),
rootMargin: '5px',
threshold: 0.5
}
let callback = function(entries, observer){
...
}
let observer = new IntersectionObserver(callback, options)
الإعدادات:- الجذر - عنصر يعمل كإطار عرض للهدف (أصل العنصر الهدف أو فارغ لإطار العرض)
- 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→ جيثباستبدال الصورة
المهمة: قم بتغيير صورة العنصر النائب إلى الأصل عندما يقوم المستخدم بتمرير الصفحة.الرمز: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→ جيثبتغيير خلفية الحاوية
المهمة: لتغيير خلفية الحاوية عندما يقوم المستخدم بتمرير الصفحة هناك والعودة.الرمز: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→ جيثبالعمل بالفيديو
المهمة: أوقف تشغيل الفيديو مؤقتًا وابدأ تشغيله مرة أخرى اعتمادًا على الفيديو الذي يقع في منطقة العرض.الرمز: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→ جيثبتقدم عرض الصفحة
المهمة: إظهار تقدم عرض الصفحة أثناء قيام المستخدم بتمرير الصفحة.الرمز:
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 divs.← Codepen→ جيثبتمرير لانهائي
المهمة: تنفيذ قائمة لا نهائية.الرمز: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 عنصر قائمة. العنصر الأخير خارج إطار العرض.
عند محاولة الوصول إلى العنصر الأخير ، يتم إنشاء عنصر جديد (أخير) مخفي عن المستخدم. وهكذا إلى ما لا نهاية.← Codepen→ جيثبتغيير حجم الطفل عند تغيير حجم أحد الوالدين
المهمة: تحديد اعتماد حجم عنصر على آخر.الرمز:
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'
}
})
النتيجة:
الحالة الأولية.
عند تقليل عرض العنصر الأصل ، يقل عرض العنصر الفرعي. في الوقت نفسه ، تساوي المسافة بينهما دائمًا تقريبًا 50 بكسل ("تقريبًا" يرجع إلى تنفيذ الآلية العكسية).← Codepen→ جيثبالعمل مع الرسوم المتحركة
المهمة: تحريك كائن عندما يكون مرئيًا.الرمز:
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'))
النتيجة:
نرى جزءًا من رأس بارت. ضغط بارت على الجانب الأيسر من منطقة العرض.
إذا وقع أكثر من 50٪ من بارت في منطقة العرض ، ينتقل إلى الوسط. عندما يغادر أكثر من 50٪ من بارت منطقة العرض ، فإنه يعود إلى موضعه الأولي.→ Codepen→ Githubشكرا لكم على اهتمامكم.