Есть ли возможность оптимизировать анимацию нескольких блоков при скроллинге?

Написал скрипт, который анимирует несколько блоков при скроллинге. Добавил в 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>


Ответы (0 шт):