首页 > 解决方案 > IntersectionObserver + 滚动事件监听器

问题描述

我将 IntersectionObserver 与滚动事件监听器混合使用。只是为了解释一下:该函数正在根据滚动位置为 CSS 变量设置动画。

我为了防止浏览器在每次滚动时触发,即使我不在元素附近,我正在做这样的事情:

if (entry.isIntersecting) {
  window.addEventListener('scroll', moduleAnimation, true);
} else {
  window.removeEventListener('scroll', moduleAnimation, true);
}

我希望功能 moduleAnimation 仅在条目相交时才监听滚动。它工作正常,除了removeEventListener.

我做错了什么?:)

非常感谢 !

编辑:这是我的完整功能:

    function stickyModule() {
    document.querySelectorAll('.full-module__img').forEach(function (module) {
        new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {

                let textOffset = module.parentElement.querySelector('.full-module__copy-wrapper').offsetTop;
                module.parentElement.parentElement.style.setProperty('--offsetWrapper', textOffset + "px");

                function moduleAnimation() {
                    console.log('scroll event');
                    let targetBrightness = 0.2;
                    let targetGrayscale = 1;
                    let targetContrast = 1.2;
                    let ImgDistFromTopDoc = Math.floor(module.parentElement.getBoundingClientRect().top + window.pageYOffset);
                    let toScroll = (window.pageYOffset - ImgDistFromTopDoc) / (module.offsetHeight - textOffset);
                    let scrollGrayscale = toScroll * targetGrayscale;
                    let scrollBrightness = 1 - toScroll * (1 - targetBrightness);
                    let scrollConstrast = 1 + toScroll * (targetContrast - 1);
                    if (toScroll < 0) {
                        module.style.setProperty('--grayscale', "0")
                        module.style.setProperty('--brightness', "1")
                        module.style.setProperty('--contrast', "1")
                    } else if (toScroll < 1 && toScroll > 0) {
                        module.style.setProperty('--grayscale', scrollGrayscale.toFixed(2))
                        module.style.setProperty('--brightness', scrollBrightness.toFixed(2))
                        module.style.setProperty('--contrast', scrollConstrast.toFixed(2))
                    } else if (toScroll > 1) {
                        module.style.setProperty('--grayscale', targetGrayscale)
                        module.style.setProperty('--brightness', targetBrightness)
                        module.style.setProperty('--contrast', targetContrast);
                    }
                }
                window.scrollTo(window.scrollX, window.scrollY + 1);
                window.scrollTo(window.scrollX, window.scrollY - 1);

                if (entry.isIntersecting) {
                    window.addEventListener('scroll', moduleAnimation, true);
                    window.addEventListener('resize', moduleAnimation, true);
                    console.log('if');
                }
                else{
                    window.removeEventListener('scroll', moduleAnimation, true);
                    console.log('else');
                }
            });
        }).observe(module);
    })
} 
    document.addEventListener('DOMContentLoaded', stickyModule);

我对 JS 有点陌生,抱歉如果我的代码看起来很疯狂哈哈

标签: javascriptintersection-observer

解决方案


removeEventListener您必须使用与在中使用的完全相同的功能addEventListener。相同的定义是不够的。

在您的示例中,moduleAnimation每次观察者触发时,您都会为每个条目重新制作。看起来是同一个功能,但它是一个全新的同名同义词。相反,您可以将函数声明移到观察者的回调之外。

function stickyModule() {
    document.querySelectorAll('.full-module__img').forEach(function (module) {
        function moduleAnimation() {
            console.log('scroll event');
        }

        new IntersectionObserver((entries, observer) => {
            entries.forEach(entry => {
                console.log('entry', entry.isIntersecting)

                if (entry.isIntersecting) {
                    window.addEventListener('scroll', moduleAnimation, true);
                    console.log('if');
                } else {
                    window.removeEventListener('scroll', moduleAnimation, true);
                    console.log('else');
                }
                
            });
        }).observe(module);
    })
} 

document.addEventListener('DOMContentLoaded', stickyModule);
body {
    height: 200vh;
}
<img src="https://via.placeholder.com/150" alt="" class="full-module__img">

将其移到循环中使其仍然具有 each 的范围module,但每次观察者触发时都会使实例保持不变。


推荐阅读