Reputation: 39
I'm using a mix of IntersectionObserver with a scroll eventListener. Just to explain: The function is animating a CSS variable based on scroll position.
I order to prevent the browser to fire each time I scroll, even though I'm not near the element, I'm doing to do something like this :
if (entry.isIntersecting) {
window.addEventListener('scroll', moduleAnimation, true);
} else {
window.removeEventListener('scroll', moduleAnimation, true);
}
I want the function moduleAnimation to listen to scroll only when the entry is intersecting. It works fine, except for the removeEventListener
.
What did I do wrong? :)
Thanks a lot !
EDIT : Here's my complete feature:
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);
I kinda new with JS sorry If my code seems crazy haha
Upvotes: 1
Views: 2259
Reputation: 2270
You have to use the exact same function in removeEventListener
that you used in addEventListener
. The same definition isn't enough.
In your example, you remake moduleAnimation
for every entry every time the observer fires. It looks like it's the same function, but it's a brand new one with the same name and same definition. Instead, you can move the function declaration outside of the observer's callback.
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">
Moving it out into the loop makes it still have scope with each module
, but leaves the instance the same for each time the observer fires.
Upvotes: 4