滚动事件的触发方式比我想要的更多。如果向下滚动(后跟动画)并摆脱当前Element的.swap类,则它所要做的就是将.swap类赋予下一个同级对象。同样的东西只是向上。现在发生的是,基本上,如果向下/向上滚动,它会转到最后一个元素,第一个元素。
我已经尝试了Debouncing,Throtling和requestAnimationFrame,但到目前为止尚未成功。
非常感谢!
HTML:
<div class="div1 swap">
<h1>Hello</h1>
</div>
<div class="div2">
<h1>Stack</h1>
</div>
<div class="div3">
<h1>Overflow</h1>
</div>
<div class="div4">
<h1>Please</h1>
</div>
<div class="div5">
<h1>Help</h1>
</div>
JS:
window.onscroll = function(event) {
var aktiv = document.querySelector('.swap');
if(this.oldScroll > this.scrollY){
console.log("Up");
aktiv.previousElementSibling.classList.toggle('swap')
aktiv.classList.toggle('swap')
}
else{
console.log("Down");
aktiv.nextElementSibling.classList.toggle('swap')
aktiv.classList.toggle('swap')
}
this.oldScroll = this.scrollY;
}
添加一些滚动距离阈值,即使现在滚动1像素也是如此。您显示下一个元素。
window.onscroll = function(event) {
var aktiv = document.querySelector('.swap');
var diff = this.oldScroll - this.scrollY;
var delta = 100; // Or some element height
// If scolled too little - do nothing
if (Match.abs(diff) <= delta) {
return;
}
if(diff < 0){
console.log("Up");
aktiv.previousElementSibling.classList.toggle('swap')
aktiv.classList.toggle('swap')
}
else{
console.log("Down");
aktiv.nextElementSibling.classList.toggle('swap')
aktiv.classList.toggle('swap')
}
this.oldScroll = this.scrollY;
}
要去抖动事件,请使用setTimeout
:
var timer;
window.onscroll = function (event) {
var self = this;
clearTimeout(timer);
timer = setTimeout(function () {
[...rest of code...]
}, 50)
}
您不应为此使用滚动事件侦听器,最好使用Intersection Observer (IO)完成此操作。
如果要在一个以上的元素上触发动画,则通过滚动事件侦听器观看这些多个元素会导致性能下降。参见example this question。免责声明:这个问题也有我的答案。
为了以现代,高性能的方式解决此问题,最好为此使用Intersection Observer (IO)。
有了IO,您可以观看一个(或多个)元素,并在它们出现或彼此相交时做出反应。
要使用IO,首先必须为其设置选项,然后定义要监视的元素,最后定义一旦IO触发将发生什么情况。
示例(Taken from here),进行了最小的修改:即使动画尚未发生,作者也删除了IO。我将unobserve调用移到了check元素是否可见的内部。
const SELECTOR = '.watched';
const ANIMATE_CLASS_NAME = 'animated';
const animate = element => (
element.classList.add(ANIMATE_CLASS_NAME)
);
const isAnimated = element => (
element.classList.contains(ANIMATE_CLASS_NAME)
);
const intersectionObserver = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
// when element's is in viewport,
// animate it!
if (entry.intersectionRatio > 0) {
animate(entry.target);
// remove observer after animation
observer.unobserve(entry.target);
}
});
});
// get only these elements,
// which are not animated yet
const elements = [].filter.call(
document.querySelectorAll(SELECTOR),
element => !isAnimated(element, ANIMATE_CLASS_NAME)
);
//console.log(elements);
// start observing your elements
elements.forEach((element) => intersectionObserver.observe(element));
.h100 {
height: 100vh;
}
.watched {
opacity: 0;
transition: opacity .5s;
}
.watched.animated {
opacity: 1;
}
<div class="h100">
scroll down
</div>
<div class="watched">
I'm watched
</div>
<div class="h100">
Another element, keep scrolling
</div>
<div class="watched">
I'm also watched
</div>