Анимация при прокрутке страницы на JavaScript и CSS

Испокон веков, всякий раз, когда вы прокручивали страницу, полную различного контента, ничего восхитительного не происходило. Контент, который попадал в поле зрения просто появлялся. А тот, который был прокручен — попросту исчезал из виду.
С нововведениями в CSS и DOM API перед каждым пользователем открываются новые горизонты для создания анимации при скролле. Но давайте меньше говорить и больше делать. Предлагаю ознакомиться с таким примером:
Обратите внимание на то, что происходит, когда вы начинаете скроллить страницу. В зависимости от того, как быстро вы будете скроллить, и какой контент на данный момент является видимым на странице, вы сможете увидеть различные виды анимации, например, как меняется цвет фона, каким образом контент появляется на странице и многое другое.
Все эти виды анимации, которые проявляют себя во время прокрутки страницы пользователем, имеют довольно скучное и незапоминающееся название – анимация, активируемая при скроллинге.
Изучив эту статью, вы сможете узнать практически все о таком виде анимации для веб-страниц и, собственно, как внедрить ее использование в реальную жизнь. Способ, с помощью которого мы будем учиться, базируется на определении текущей проблемы, которую нужно решить.
После уточнения всех деталей мы сможем определиться, каким все же должен быть конечный результат. Далее мы изучим некоторые отрывки кода, прежде чем перейдем к практической части решения заданий. Это делается для того, чтобы понять, как все части кода работают вместе, и как вышеприведенный пример вообще функционирует. Это действительно должно быть интересным, так давайте начнем!

Идея

Способ, по которому работает данный вид анимации, довольно прост с одной стороны и сложен с другой. Более легкий этап включает в себя сбор в одно целое нескольких технических моментов. Сложность же заключается в том, как именно все будет взаимодействовать между собой, чтобы у пользователя действительно создалось впечатление, что перед ним – единый и проработанный объект, готовый к взаимодействию.

Контент

Начиная с самого верха веб-страницы, первое, что видит пользователь, это контент:

Почти все веб-страницы, кроме тех, которые имеют специфический дизайн, будут иметь контента больше, чем может вместиться на первый экран. Чтобы увидеть всю страницу нам приходиться ее скроллить. Теперь переходим ко второму шагу.

Время скроллить

Контент, расположенный на любой веб-странице, является автономным, но способ просмотра данного контента зависит от вашего браузера (или других параметров).
Всякий раз, когда браузер видит больше контента, чем он может отобразить за один раз, он будет давать вам возможность прокрутить содержимое текущей веб-страницы:

Прокрутить страницу мы можем с помощью тактильных жестов на экране вашего смартфона, посредством мыши, нажатия на клавиатуру или прокрутки скроллбара, а так же любым другим доступным на сегодняшний день способом.
Поэтому мы хотим усовершенствовать существующий контент так, чтобы его элементы при скроллинге изменяли свой вид различными способами.

Идентификация элементов

Скорее всего, это самая сложная часть в создании активной анимации. Ранее мы говорили в целом, что будем работать с контентом. Наш контент на самом деле состоит из различных HTML элементов, отображение многих из которых зависит от того, каким образом они расположены на веб-странице и как взаимодействуют друг с другом.
В любом случае, только подмножество таких элементов будет видимым на вашем экране в конкретный момент времени:

Во время скороллинга подмножество видимых элементов будет меняться:

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

Другой же заключается в том, что определяет полноту отображения тех или иных элементов на странице:

Несмотря на то, что на данный момент довольно сложно ощутить разницу между этими двумя методами (при написании кода), результат, который они обеспечивают на практике, сможет расставить все точки над «i».

Изменение элементов

После того, как вы идентифицировали элементы, с которыми собираетесь работать, остается все же что-то сделать с этими элементами. В то время, как главной темой данного урока является научить вас анимировать элементы веб-страницы, практическое же решение данной задачи является более универсальным.
Это решение базируется на создании значений класса видимых (в конкретный момент времени) элементов. Теперь у нас одна задача: активировать любой из стилей CSS, который сможет в дальнейшем управлять прокручиваемыми элементами на данной веб-странице. Это основная концепция моделирования элементов с помощью JavaScript.
Давайте более детально рассмотрим на примере. Для начала, используем некоторые элементы из списка:

  1. One
  2. Two
  3. Three
  4. Four
  5. Five
  6. Six
  7. Seven
  8. Eight
  9. Nine
  10. Ten

Эти элементы имеют следующий стиль:

#myList li {
    padding-left: 7px;
    margin-bottom: 15px;
    transition: all .2s ease-in-out;
    transform: translate3d(0px, 30px, 0);
    opacity: 0;
}
#myList li.active {
    transform: translate3d(0px, 0, 0);
    opacity: 1;
}

В нашем списке элементов есть только параметр стиля #myList Li, который и будет применяться к ним. При скроллинге мы хотим добиться того, чтобы видимые элементы и невидимые по-разному отображались на странице, поэтому стоит применить к ним такие свойства (видимые элементы веб-страницы обозначаем, как активные):

  1. One
  2. Two
  3. Three
  4. Four
  5. Five
  6. Six
  7. Seven
  8. Eight
  9. Nine
  10. Ten

Причина, по которой мы делаем это, не позволяет установить различный вид наших элементов в HTML коде. По крайней мере, это не конечная цель, которую мы преследуем. Наша цель – сделать так, чтобы данные элементы имели разные стили. В тот момент, когда наши элементы, расположенные на веб-странице, получают активный статус, параметр стилей #myList li.active применяется к ним. Это ключевой момент, когда видимые элементы отличаются от невидимых (которым не присваивается никакое значение).
Остальное за заливкой. Говоря более точно, на странице мы видим то, что прописано в HTML и CSS. Если следовать примеру, то когда стиль #myList li.active является активным, видимые элементы станут анимированными. Проверить это можно с помощью такого кода, прописанного в CSS:

#myList li {
    padding-left: 7px;
    margin-bottom: 15px;
    transition: all .2s ease-in-out;
    transform: translate3d(0px, 30px, 0);
    opacity: 0;
}
#myList li.active {
    transform: translate3d(0px, 0, 0);
    opacity: 1;
}

Если визуализировать вышеуказанное, то мы получим примерно следующее:

Довольно важно отметить, что будет происходить в зависимости от свойств CSS стиля, которые применены к тому или иному элементу на веб-странице. Видимые элементы получают лишь сигнал. Как именно будет реагировать CSS стиль, зависит только от того, какие параметры в коде вы зададите. Создание анимации, которая активируется при прокрутке экрана – лишь один пункт из большого списка ваших возможностей.

Создание структуры

В предыдущих этапах мы познакомились с различными путями создания анимированного контента при скроллинге. Далее мы сможем ознакомиться с информацией, которая поможет понять, как взаимодействует JavaScript с нашими видимыми элементами.

Создание события прокрутки

Прежде всего, с помощью JavaScript мы сможем определить момент прокрутки пользователем веб-страницы. Всякий раз, когда вы прокручиваете страницу используя скроллбар (или пальцы на сенсорном устройстве), ваш браузер запускает событие прокрутки. Вот самый простой способ проверить это:

window.addEventListener("scroll", dealWithScrolling, false);
 
function dealWithScrolling(e) {
    // do epic stuff    
}

Каждый раз, когда вы скроллите в окне браузера, вызывается обработчик событий dealWithScrolling. Выглядит довольно просто, не так ли?
Но существует небольшая проблема с данным подходом. Данное событие вызывается при очень большой частоте, поэтому вам нужно не допустить конфликта с DOM (объектной моделью документа). Вы можете использовать setTimeOut или setInterval, чтобы определить задержку реакции браузера на обработку того или иного события, но лучше привязать данные параметры к частоте обновления кадров страницы. Это может быть осуществлено с помощью метода requestAnimationFrame.
Советуем взглянуть на следующий фрагмент:

var isScrolling = false;
 
window.addEventListener("scroll", throttleScroll, false);
 
function throttleScroll(e) {
    if (isScrolling == false ) {
        window.requestAnimationFrame(function() {
          dealWithScrolling(e);
          isScrolling = false;
        });
    }
    isScrolling = true;
}   
 
function dealWithScrolling(e) {
    // do epic stuff    
}

Конечный результат этого кода идентичен к тому подходу, который мы рассматривали ранее в статье. Как только страница начинает прокручиваться, вызывается обработчик событий dealWithScrolling. Разница лишь в том, что наш обработчик событий не будет вызван раньше, чем метод requestAnimationFrame. Это значит, что текущий обработчик событий будет вызван около 60 раз в секунду, что является допустимым значением при работе с DOM структурами различного рода.

Определение видимых элементов

Только некоторые фрагменты кода позволят вам выяснить, какие из элементов на текущей веб-странице можно считать видимыми при скроллинге. Чтобы это осуществить, используем метод getBoundingClientRect. Этот метод возвращает некий прямоугольник, который ограничивает ту самую видимую область, со значениями относительно верха, низа страницы, левого и правого направлений, а также относительно левого верхнего угла браузера и его основных свойств (ширины и высоты окна). Другими вашими помощниками будут выступать свойства window.innerHeight window.innerWidth, которые возвращают высоту и ширину окна браузера соответственно.
Для визуализации полученных сведений рекомендуем ознакомиться с данной диаграммой:

Потратьте несколько минут на изучение данной диаграммы, чтобы понять какие методы позволяют вам определить видимые элементы. После того, как вы пройдете этот этап, рекомендуем ознакомиться с кодом, который позволит улучшить знания для более детального понимания процесса, который изображен в диаграмме.

Определение частично видимых элементов

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

function isPartiallyVisible(el) {
    var elementBoundary = el.getBoundingClientRect();
 
    var top = elementBoundary.top;
    var bottom = elementBoundary.bottom;
    var height = elementBoundary.height;
 
    return ((top + height >= 0) && (height + window.innerHeight >= bottom));
}

В качестве аргумента функции нам необходимо передать элемент. Если элемент частично видимый, функция вернет true. Иначе, функция вернет false.

Определение полностью видимых элементов

Чтобы определить, является ли элемент полностью видимым, вы можете использовать функцию isFullyVisible:

function isFullyVisible(el) {
  var elementBoundary = el.getBoundingClientRect();
 
  var top = elementBoundary.top;
  var bottom = elementBoundary.bottom;
 
  return ((top >= 0) && (bottom < = window.innerHeight));
}

Данная функция работает аналогично к isPartiallyVisible функции, которая была описана ранее. Если элемент определился, как полностью видимый, то функция isFullyVisible вернет значение true, если же данный элемент оказался частично видимым для пользователя, то наша функция вернет значение false.

Собираем все воедино

Если вы дошли до этой части статьи, то наверняка поняли, как разнообразить контент на сайте, чтобы при скроллинге страницы он был динамичным. Также вы ознакомились со сложными фрагментами кода, которые должны взаимодействовать между собой корректно, чтобы осуществить вашу задумку. Кроме того, вы узнали, что дают функции isFullyVisible и isPartiallyVisible. Чтобы увидеть, как эти все фрагменты кода работают вместе, вы можете посмотреть исходный пример здесь.
Если вы хотите изучить полный код (HTML, JS, CSS) для нашего примера, рекомендуем вам ознакомиться со следующими материалами:

 

  
  Change Color on Scroll
 
  
    body {
      background-color: #FDE74C;
      transition: all 1s ease-in;
      padding: 50px;
      color: #111;
      font-family: sans-serif;
      line-height: 32px;
      font-size: 18px;
    }
 
    h1 {
      font-family: sans-serif;
    }
 
    .colorOne {
      background-color: #9BC53D;
      color: #000;
    }
 
    .colorTwo {
      background-color: #FFF;
      color: #000;
    }
 
    #mainContent {
      width: 420px;
      margin: 0 auto;
    }
 
    #mainContent p {
      padding: 20px;
    }
 
    #mainContent #firstBox {
      font-weight: bold;
      transform: translate3d(-30px, 0, 0);
      transition: all .5s ease-out;
      opacity: 0;
    }
 
    #mainContent #firstBox.active {
      background-color: #333;
      color: #FFF;
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
 
    #mainContent #secondBox {
      transition: all .2s ease-in-out;
      transform: translate3d(0, 30px, 0);
      opacity: 0;
    }
 
    #mainContent #secondBox.active {
      background-color: #1581AF;
      color: #FFF;
      transform: translate3d(0, 0, 0);
      opacity: 1;
    }
 
    #mainContent ol li {
      padding-left: 7px;
      margin-bottom: 15px;
      transition: all .2s ease-in-out;
      transform: translate3d(20px, 0, 0);
      opacity: 0;
    }
 
    #mainContent ol li.active {
      transform: translate3d(0px, 0, 0);
      opacity: 1;
    }
  

 

  

Scroll Down

    
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur quis massa a arcu efficitur suscipit vehicula et risus.
  1. Nam sagittis est non enim ultrices elementum.
  2. Sed id ligula sed mi tempor ornare.
  3. Aenean feugiat risus eget sagittis volutpat. Proin quis orci a metus lacinia auctor eget id nisi.
  4. Donec pulvinar nunc feugiat semper consequat.
  5. Etiam cursus justo eget libero gravida, nec faucibus mauris posuere.
  6. In nec sem id libero egestas cursus vel a urna.
  7. Fusce pulvinar arcu eu lobortis egestas. Maecenas eleifend felis ut urna consectetur, et pellentesque mi molestie.
  8. Aliquam ut felis venenatis, dapibus ante non, gravida nulla.
  9. Donec consectetur quam in urna commodo, sed aliquet metus vehicula.
  10. Mauris eget est sit amet felis eleifend sagittis non id nulla.
    
Phasellus tortor nisl, dapibus at posuere sed, tempor in massa. Pellentesque eu sodales orci, finibus congue libero. Mauris molestie bibendum posuere.
    
Nunc blandit varius sapien quis ultrices. Vestibulum et consequat augue. Pellentesque et maximus nisl, sit amet dictum ante.
    
Nullam magna augue, consequat eu augue ut, volutpat fringilla est. Ut commodo ac magna vulputate dictum.
  
 
  
    var isScrolling = false;
 
    window.addEventListener("scroll", throttleScroll, false);
 
    function throttleScroll(e) {
      if (isScrolling == false) {
        window.requestAnimationFrame(function() {
          scrolling(e);
          isScrolling = false;
        });
      }
      isScrolling = true;
    }
 
    document.addEventListener("DOMContentLoaded", scrolling, false);
 
    var listItems = document.querySelectorAll("#mainContent ol li");
    var firstBox = document.querySelector("#firstBox");
    var secondBox = document.querySelector("#secondBox");
 
    function scrolling(e) {
 
      if (isPartiallyVisible(firstBox)) {
        firstBox.classList.add("active");
 
        document.body.classList.add("colorOne");
        document.body.classList.remove("colorTwo");
      } else {
        document.body.classList.remove("colorOne");
        document.body.classList.remove("colorTwo");
      }
 
      if (isFullyVisible(secondBox)) {
        secondBox.classList.add("active");
 
        document.body.classList.add("colorTwo");
        document.body.classList.remove("colorOne");
      }
 
      for (var i = 0; i < listItems.length; i++) {
        var listItem = listItems[i];
 
        if (isPartiallyVisible(listItem)) {
          listItem.classList.add("active");
        } else {
          listItem.classList.remove("active");
        }
      }
    }
 
    function isPartiallyVisible(el) {
      var elementBoundary = el.getBoundingClientRect();
 
      var top = elementBoundary.top;
      var bottom = elementBoundary.bottom;
      var height = elementBoundary.height;
 
      return ((top + height >= 0) && (height + window.innerHeight >= bottom));
    }
 
    function isFullyVisible(el) {
      var elementBoundary = el.getBoundingClientRect();
 
      var top = elementBoundary.top;
      var bottom = elementBoundary.bottom;
 
      return ((top >= 0) && (bottom
Понравилась статья? Поделиться с друзьями:
WordPress-Блог
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: