دراسات حالة API التقاطع المراقب



يوم جيد يا اصدقاء!

نظرة عامة


تسمح واجهة 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 => {
        // entry () - 
        //   entry.boundingClientRect
        //   entry.intersectionRatio
        //   entry.intersectionRect
        //   entry.isIntersecting
        //   entry.rootBounds
        //   entry.target
        //   entry.time
    })
}

الشبكة مليئة بالمعلومات حول النظرية ، ولكن القليل من المواد حول ممارسة استخدام 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)

    //       img  
    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)
                //        "data-src"
                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')
    // ratio -   
    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)
    
    //    
    //      20 ,   
    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()
        //      (   > 0)
        } else if(video.currentTime != 0) {
            //  
            video.play()
        }
    }, { threshold: 0.4 })

    observer.observe(video)
}

النتيجة:



أثناء تشغيل الفيديو في منطقة العرض ، يتم تشغيله.



بمجرد أن يتجاوز الفيديو منطقة العرض بأكثر من 40٪ ، يتوقف تشغيله مؤقتًا. إذا ضربت منطقة العرض> 40٪ من الفيديو ، فسيستأنف تشغيله.

Codepen

→  جيثب

تقدم عرض الصفحة


المهمة: إظهار تقدم عرض الصفحة أثناء قيام المستخدم بتمرير الصفحة.

الرمز:

//          
let p = document.querySelector('p')
// n -   
let n = 0

let observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
        if(entry.isIntersecting){
            // observer   div
            //       
            //     
            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)
}

//  ,        
//     
//         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')
//     50px  
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 => {
        //         50px
        if ((entry.target.parentElement.offsetWidth - entry.target.offsetWidth) < 50) {
            //     50px
            entry.target.style.width = entry.target.offsetWidth - 50 + 'px'
        }
    })
}, options)

observer.observe(child)

//  ,  ,       IOA
//       resize
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

شكرا لكم على اهتمامكم.

All Articles