DevGang
Авторизоваться

Изменение цвета фона при прокрутке с помощью JavaScript

В последнее время анимация прокрутки становится все более популярной тенденцией, особенно на целевых страницах SaaS и современных технологических стартапов. Эти анимации призваны украсить пользовательский интерфейс, если только они грамотно закодированы и не слишком навязчивы для конечного пользователя.

Ранее мы уже создавали учебные пособия по этой теме, например, по анимации "водопада" карточек при прокрутке или по градиентному раскрытию текста. Сегодня мы добавим к этому списку еще один пример: изменение цвета фона страницы при прокрутке.

Этот эффект позволит придать дизайну динамичность и сделать каждый раздел уникальным.

Структурирование HTML

В этом демонстрационном примере мы создадим элемент <main> с четырьмя секциями, каждая из которых будет связана с отдельным цветом из палитры Tailwind: Sky 200, Purple 200, Pink 200 и Emerald 200.

Чтобы обеспечить плавные цветовые переходы, мы не будем напрямую применять цвета фона к отдельным разделам. Вместо этого мы воспользуемся API Intersection Observer для определения доминирующей секции и применим соответствующий цвет фона к основному контейнеру.

Вот основная структура HTML:

<main class="relative min-h-screen flex flex-col bg-sky-200 overflow-hidden">
    <div class="w-full max-w-5xl mx-auto px-4 md:px-6">
        <div class="pt-6 pb-12 md:pt-10 md:pb-20">

            <!-- Sky section -->
            <section>
                <!-- ... content ... -->
            </section>

            <!-- Purple section -->
            <section>
                <!-- ... content ... -->
            </section>

            <!-- Pink section -->
            <section>
                <!-- ... content ... -->
            </section>

            <!-- Emerald section -->
            <section>
                <!-- ... content ... -->
            </section>

        </div>
    </div>
</main>

Мы установили цвет фона элемента <main> по умолчанию на Sky 200 (bg-sky-200, это цвет первой секции) и убедились, что он заполняет по крайней мере высоту области просмотра с помощью min-h-screen.

Создание JS-класса

Создадим в корне проекта файл bg-scroll.js и включим его в наш HTML-документ:

<script src="./bg-scroll.js"></script>

В этом файле мы определим класс с именем BgScroll, который будет содержать метод init для инициализации наблюдателя. Вот код для начала:

class BgScroll {
  constructor(element) {
    this.element = element;
    this.init();
  }

  init() {
  }
}

// Init BgScroll
const el = document.querySelector('[data-bg-scroll]');
new BgScroll(el);

В конце файла мы указываем, как инициализировать класс, добавляя атрибут data-bg-scroll к элементу <main> в HTML:

<main class="relative min-h-screen flex flex-col bg-sky-200 overflow-hidden" data-bg-scroll>

Создание наблюдателя

Теперь напишем код для инициализации наблюдателя:

class BgScroll {
  constructor(element) {
    this.element = element;
    this.sections = this.element.querySelectorAll('section');
    this.observeSection = this.observeSection.bind(this);
    this.init();
  }

  observeSection(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        console.log(entry.target);
      }
    });
  }  

  init() {
    const observer = new IntersectionObserver(this.observeSection, { rootMargin: '-50% 0% -50% 0%' });
    this.sections.forEach(section => {
      observer.observe(section);
    });
  }
}

// Init BgScroll
const el = document.querySelector('[data-bg-scroll]');
new BgScroll(el);

В конструкторе мы создали новый экземпляр с именем sections, который содержит массив всех секций внутри основного элемента. В методе init() мы проходим по этому массиву и создаем нового наблюдателя для каждой секции.

Первым аргументом IntersectionObserver является обратный вызов, который будет выполняться каждый раз, когда секция входит или выходит из области просмотра (т.е. observeSection). Второй аргумент - объект options, который содержит свойство rootMargin. Используя значения -50% 0% -50% 0%, мы указываем IntersectionObserver на то, что обратный вызов должен срабатывать, когда секция пересекает воображаемую горизонтальную линию, расположенную на расстоянии 50% от верхней границы области просмотра.

Для тестирования мы добавили console.log внутри метода observeSection, чтобы определить доминирующую секцию при прокрутке.

Изменение цвета фона

Теперь, когда мы знаем, какой раздел является доминирующим, мы можем применить соответствующий цвет фона к элементу <main>.

Для этого мы определим цвет фона каждой секции с помощью атрибута data-bg-color и класса Tailwind соответствующего цвета фона:

<main class="relative min-h-screen flex flex-col bg-sky-200 overflow-hidden" data-bg-scroll>
    <div class="w-full max-w-5xl mx-auto px-4 md:px-6">
        <div class="pt-6 pb-12 md:pt-10 md:pb-20">

            <!-- Sky section -->
            <section data-bg-class="bg-sky-200">
                <!-- ... content .... -->
            </section>

            <!-- Purple section -->
            <section data-bg-class="bg-purple-200">
                <!-- ... content .... -->
            </section>

            <!-- Pink section -->
            <section data-bg-class="bg-pink-200">
                <!-- ... content .... -->
            </section>

            <!-- Emerald section -->
            <section data-bg-class="bg-emerald-200">
                <!-- ... content .... -->
            </section>

        </div>
    </div>
</main>

Теперь внутри метода observeSection мы можем получить значение атрибута entry.target.dataset.bgClass и применить его к основному элементу:

class BgScroll {
  constructor(element) {
    this.element = element;
    this.sections = this.element.querySelectorAll('section');
    this.observeSection = this.observeSection.bind(this);
    this.init();
  }

  observeSection(entries) {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        // Remove all bg classes
        this.element.classList.forEach(className => {
          if (className.startsWith('bg-')) {
            this.element.classList.remove(className);
          }
        });
        // Add the proper bg class
        this.element.classList.add(entry.target.dataset.bgClass);
      }
    });
  }  

  init() {
    const observer = new IntersectionObserver(this.observeSection, { rootMargin: '-50% 0% -50% 0%' });
    this.sections.forEach(section => {
      observer.observe(section);
    });
  }
}

// Init BgScroll
const el = document.querySelector('[data-bg-scroll]');
new BgScroll(el);

И, как вы уже догадались, мы также удаляем все классы, начинающиеся с bg-, чтобы обеспечить применение только одного фонового класса.

Добавление анимации затухания

Для завершения эффекта мы добавим анимацию затухания к изменению цвета фона. Для этого достаточно добавить класс transition-colors в элемент <main> таким образом:

<main class="relative min-h-screen flex flex-col bg-sky-200 transition-colors duration-700 overflow-hidden" data-bg-scroll>

Мы также добавили класс duration-700, позволяющий увеличить длительность анимации для получения более плавного эффекта.

Заключение

Создать этот динамический фоновый эффект с помощью Intersection Observer невероятно просто. Он занимает всего около 30 строк JavaScript, и никаких внешних библиотек не требуется.

Не стесняйтесь проводить собственные эксперименты и изменять код в соответствии со своими потребностями.

Источник:

#JavaScript #HTML
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу