Изменение фона элемента при прокрутке на основе текущего раздела и оптимизации производительности

#javascript

#javascript

Вопрос:

Идея состоит в том, чтобы изменить .wrapper фон в зависимости от текущего раздела. К сожалению, есть некоторые ограничения. Мне нужно изменить его на основе текущего window.scrollTop , section.offsetTop а НЕ того, какой раздел находится в окне просмотра в данный момент. (IntersectionObserver не будет работать)

Это будет что-то вроде scrollSpy, но я не могу перебирать все разделы в каждом событии прокрутки из-за соображений производительности. Кроме того, я использую плагин виртуальной прокрутки для плавной прокрутки, который выполняет еще больше вычислений при прокрутке.

К коду, который у меня есть на данный момент:

Мои разделы выглядят так:

 <section class="intro"
  data-bg="#ffffff"
  data-color="#1A1919"
>
  Section content goes here
</section>
  

У меня есть массив объектов. В каждом объекте у меня есть элемент узла и его вершина.

 const sections = [
  {
    el: section.intro, // Node
    top: 1224 // Number
  },
  ....
]
  

Я могу взять scrollTop из плагина при прокрутке. Итак, код на данный момент выглядит следующим образом:

 const wrapper = document.querySelector('.wrapper');

const changeBg = (scrollTop, sections) => {
  sections.map(({ el, top }) => {
    const bg = el.getAttribute('data-bg');
    const color = el.getAttribute('data-color');

    if (top < scrollTop   window.innerHeight) {
      console.log(bg);
      wrapper.style.backgroundColor = bg;
      wrapper.style.color = color;
    }
  });
};

myCustomPluginForScroll.on('scroll', e => {
  const { y } = e.scroll;

  changeBg(y, sections);
});
  

Проблемы заключаются в:

  1. Я перебираю все разделы при каждом событии прокрутки (которое умножается на многие из плагина для обеспечения плавной прокрутки), и это вызывает задержку при прокрутке;
  2. По мере прокрутки вниз все больше и больше разделов становятся действительными для условия top < y window.innerHeight , которое изменяет фон оболочки еще больше раз за прокрутку.

Я не могу использовать debouncer для выполнения меньшего количества вызовов из changeBg -за плагина smooth scroll.

На вопрос:

Как я могу вызвать changeBg только один раз, когда новый раздел добавляется / удаляется из условия top < y window.innerHeight и принимает атрибуты bg / color только в последнем добавленном / удаленном разделе.

Прикрепляем скриншот с журналом из bg 6 разделов и прокручиваем до нижней части сайта. Таким образом, при каждом прокрутке у меня есть 6 изменений фона оболочки.

скриншот с последней консоли.журнал bg

Комментарии:

1. вы можете пометить активный раздел в первый раз, а затем проверить, изменен ли раздел, прежде чем вызывать вашу фактическую логику изменений. например. addEventListener('scroll', e => { if (!sectionToChange.classList.contains('your-active-class ) { // запустите свой код …}

2. Хорошее предложение @pilchard, но код должен работать при прокрутке назад к началу, изменяя фон, связанный с атрибутом текущего раздела data-bg .

3. Это не должно быть проблемой, просто различайте направление прокрутки и соответствующим образом устанавливайте / очищайте перекраску.