Есть ли возможность оптимизировать анимацию нескольких блоков при скроллинге?
Написал скрипт, который анимирует несколько блоков при скроллинге.
Добавил в CSS свойство will-change, использовал requestAnimationFrame в JS, но это все спички, учитывая то, что при скроллинге мы итерируем массив элементов. Чем элементов в массиве больше -- тем дольше скрипт будет его обрабатывать.
Можно ли как-то оптимизировать этот процесс? Например, мне при каждом событии скролла нужно обновлять информацию о позиции элементов и, если даже предположить что у каждого блока будет свое реактивное состояние с местоположением, то оно также должно будет от чего-то отталкиваться -- обновляться по сроллу, также придется итерировать массив и обновлять все значения.
Итоговый вопрос -- как оптимизировать процесс? Как избавиться от итераций?
P.S. В песочнице какая-то проблема с версткой, но она в этом вопросе и не важна.
let ticking;
const triggerStart = (window.innerHeight / 2);
const triggerEnd = 0;
const portfolioBlocks = document.getElementsByClassName('portfolio-block');
function animatePortfolio() {
for (let i = 0; i < portfolioBlocks.length; i++) {
const block = portfolioBlocks[i];
const top = block.getBoundingClientRect().top;
if (triggerStart >= top && triggerEnd <= top) {
// const difference = triggerStart - top;
// const opacity = difference / triggerStart;
block.style = `opacity: ${(triggerStart - top) / triggerStart}`;
if (portfolioBlocks[i - 1]) {
// const blur = opacity * 5;
portfolioBlocks[i - 1].style.filter = `blur(${((triggerStart - top) / triggerStart) * 5}px)`;
}
}
}
}
window.addEventListener('scroll', () => {
if (!ticking) {
window.requestAnimationFrame(() => {
animatePortfolio();
ticking = false;
});
ticking = true;
}
});
* {
margin: 0;
padding: 0;
}
.other {
height: 500px;
}
.portfolio {
width: 100%;
}
.portfolio-block {
opacity: 0;
will-change: opacity, filter;
position: sticky;
top: 0;
width: 100%;
height: 100vh;
background: green;
}
.portfolio__text {
margin: auto;
width: 50%;
height: 50vh;
background: red;
}
<div class="other"></div>
<div class="portfolio">
<div class="portfolio-block"></div>
<div class="portfolio-block portfolio__text"></div>
<div class="portfolio-block"></div>
<div class="portfolio-block portfolio__text"></div>
</div>
<div class="other"></div>