Ломается eventListener
Есть 12 блоков. Выполняется css анимация при помощи добавления в блок определенного класса через js. нужно, чтоб каждый блок выполнял анимацию поочередно, а так же анимация происходила при скроле. проблема в том, что, когда видимые блоки в окне браузера выполнили свою анимацию, потом начинаешь скролить - ничего не происходит. А когда скролишь при незавершенной анимации - все прекрасно работает. проблема в функции animOnScroll() не срабатывает addEventListener в конце функции в местах:
if (i < animItems.length) {
animOnScroll();
} else {
window.addEventListener('scroll', animOnScroll);
}
Вот код js:
const animItems = document.getElementsByClassName("animItems");
let i = 0;
window.addEventListener('scroll', animOnScroll);
function animOnScroll() {
window.addEventListener('scroll', animOnScroll);
const animItem = animItems[i];
i++;
const animItemHeight = animItem.offsetHeight;
const animItemOffset = offset(animItem).top;
let animItemPoint = window.innerHeight;
if ((pageYOffset > animItemOffset - animItemPoint) && pageYOffset < (animItemOffset + animItemHeight)) {
animItem.classList.add('_active');
window.removeEventListener('scroll', animOnScroll);
animItem.ontransitionend = function() {
if (i < animItems.length) {
animOnScroll();
} else {
window.addEventListener('scroll', animOnScroll);
}
};
} else {
if (i < animItems.length) {
animOnScroll();
} else {
window.addEventListener('scroll', animOnScroll);
}
}
}
function offset(el) {
const rect = el.getBoundingClientRect(),
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
}
setTimeout(animOnScroll, 100);
вот css, если нужен:
.box {
width: 1100px;
}
.animItems {
display: inline-block;
position: relative;
height: 300px;
width: 300px;
background: #555;
margin: 20px;
transform: scale(0);
transition: all 1.5s ease;
}
._active {
transform: scale(1);
}
и html:
<div class="box">
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
<div class="animItems"></div>
</div>
Ответы (1 шт):
Разобрался
Оказывается, проблемы была не в eventListener, как думал я, а в том, что счетчик i после первого прохода равнялся 12 и при вторичном прогоне по циклу он начинал с числа 13, а как вы помните, блоков всего 12 и поэтому он не мог найти 13 блок по счету.
Было решено в конце цикла добавить присваивание счетчику номер последнего элемента, которому был добавлен класс _active. Выглядит вот так: i = document.getElementsByClassName('_active').length; и поместил это в те самые элементы с условием в конце:
if (i < animItems.length) {
animOnScroll();
} else {
//вот здесь
i = document.getElementsByClassName('_active').length;
window.addEventListener('scroll', animOnScroll);
}
если кому интересно, вот полный js, который у меня получился:
const animItems = document.getElementsByClassName("animItems");
let i = 0;
function animOnScroll() {
window.removeEventListener('scroll', animOnScroll);
const animItem = animItems[i];
i++;
console.log(i);
let animItemHeight = animItem.offsetHeight;
const animItemOffset = offset(animItem).top;
let animItemPoint = window.innerHeight;
if ((pageYOffset > animItemOffset - animItemPoint) && pageYOffset < (animItemOffset + animItemHeight)) {
animItem.classList.add('_active');
window.removeEventListener('scroll', animOnScroll);
animItem.ontransitionend = function() {
if (i < animItems.length) {
animOnScroll();
} else {
i = document.getElementsByClassName('_active').length;
window.addEventListener('scroll', animOnScroll);
}
};
} else {
if (i < animItems.length) {
animOnScroll();
} else {
i = document.getElementsByClassName('_active').length;
window.addEventListener('scroll', animOnScroll);
}
}
}
function offset(el) {
const rect = el.getBoundingClientRect(),
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft;
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
}
setTimeout(animOnScroll, 100);