javascript - 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 有点陌生,抱歉如果我的代码看起来很疯狂哈哈
解决方案
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
,但每次观察者触发时都会使实例保持不变。
推荐阅读
- sql-server - 更新和插入触发失败后
- microsoft-graph-api - Microsoft 团队图形 API(已加入团队)正在返回空团队结果
- javascript - 尝试使用 navigator.language 将用户重定向到 /en 时无休止的重定向循环
- kubernetes - Kubernetes Pod 卡在“终止”状态
- reactjs - 如何使用按钮重置字段,是否有更简洁的方式来编写此 React
- android - 在更改构建 gradle 后尝试几天构建我的应用程序时出现太多异常
- c - pthread_cond_signal 可以唤醒多个线程吗?
- ios - 从 tableview 到 viewcontroller 执行 segue 的问题
- java - 类型不匹配:尝试将驱动程序设置为 ITestContext 时无法从 void 转换为 ITestContext
- javascript - 在 jquery 密码显示/隐藏 if-else 条件不适用于按钮 cick