Перейти к содержимому

Анимации JavaScript

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

Введение в JavaScript-анимации

JavaScript-анимации изменяют элементы Document Object Model (DOM) для создания визуальных эффектов. Их используют для перемещения, изменения размера и преобразования элементов в ответ на действия пользователя или автоматически с течением времени. Понимая основные принципы и техники, вы сможете создавать анимации, которые будут и производительными, и визуально привлекательными.

Зачем использовать JavaScript для анимаций?

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

Основные понятия JavaScript-анимаций

Прежде чем переходить к конкретным техникам, важно понять несколько базовых понятий, лежащих в основе JavaScript-анимаций:

  1. Кадров в секунду (FPS): скорость, с которой отображаются кадры анимации. Более высокий FPS обеспечивает более плавную анимацию.
  2. Функции сглаживания: эти функции управляют ускорением и замедлением анимации, добавляя естественность движения.
  3. Функции времени: определяют длительность и задержку анимации.
  4. Ключевые кадры: задают начальное, конечное и промежуточные состояния анимации.

Простой пример JavaScript-анимации

Начнём с простого примера, в котором мы анимируем квадрат, движущийся по экрану.


html
<!DOCTYPE html>
<html>
<head>
  <style>
    #square {
      width: 50px;
      height: 50px;
      background-color: red;
      position: absolute;
      left: 0;
      top: 50px;
    }
  </style>
</head>
<body>
  <div id="square"></div>
  <script>
    const square = document.getElementById('square');
    let pos = 0;

    function move() {
      if (pos < window.innerWidth - 50) {
        pos += 2;
        square.style.transform = 'translateX(' + pos + 'px)';
        requestAnimationFrame(move);
      }
    }

    move();
  </script>
</body>
</html>

Этот пример демонстрирует базовую анимацию, в которой красный квадрат движется слева направо по экрану. Анимация использует функцию requestAnimationFrame, которая обеспечивает плавное движение, синхронизируя анимацию с частотой обновления дисплея. Функция move постепенно обновляет положение квадрата и непрерывно вызывает саму себя, пока квадрат не достигнет края окна.

INFO

Хотя JS-анимации требуют частых обновлений стилей, для предотвращения перерасчёта макета лучше использовать transform и opacity.

Продвинутые техники в JavaScript-анимациях

Использование функций сглаживания

Функции сглаживания делают анимации более естественными, изменяя скорость анимации. Обычно они ожидают нормализованное значение прогресса между 0 и 1. Вот пример использования функции сглаживания для анимации квадрата:


html
<!DOCTYPE html>
<html>
<head>
  <style>
    #square {
      width: 50px;
      height: 50px;
      background-color: blue;
      position: absolute;
      left: 0;
      top: 50px;
    }
  </style>
</head>
<body>
  <div id="square"></div>
  <script>
    const square = document.getElementById('square');
    let start = null;
    const duration = 2000; // Animation duration in milliseconds

    function easeOutQuad(t) {
      return t * (2 - t);
    }

    function animate(timestamp) {
      if (!start) start = timestamp;
      let elapsed = timestamp - start;
      let progress = Math.min(elapsed / duration, 1);
      let easedProgress = easeOutQuad(progress);

      square.style.transform = 'translateX(' + (window.innerWidth - 50) * easedProgress + 'px)';

      if (progress < 1) {
        requestAnimationFrame(animate);
      }
    }

    requestAnimationFrame(animate);
  </script>
</body>
</html>

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

Цепочка анимаций

Цепочка анимаций позволяет выполнять несколько анимаций последовательно. Вот пример квадрата, который сначала движется вправо, а затем вниз:


html
<!DOCTYPE html>
<html>
<head>
  <style>
    #square {
      width: 50px;
      height: 50px;
      background-color: green;
      position: absolute;
      left: 0;
      top: 0;
    }
  </style>
</head>
<body>
  <div id="square"></div>
  <script>
    const square = document.getElementById('square');
    let xPos = 0;
    let yPos = 0;

    function moveRight() {
      if (xPos < window.innerWidth - 50) {
        xPos += 2;
        square.style.transform = 'translateX(' + xPos + 'px)';
        requestAnimationFrame(moveRight);
      } else {
        xPos = 0;
        yPos = 0; // Explicitly reset yPos before downward phase
        square.style.transform = 'translateX(0px)';
        requestAnimationFrame(moveDown);
      }
    }

    function moveDown() {
      if (yPos < window.innerHeight - 50) {
        yPos += 2;
        square.style.transform = 'translateY(' + yPos + 'px)';
        requestAnimationFrame(moveDown);
      } else {
        yPos = 0; // Reset for repeated cycles
        requestAnimationFrame(moveRight);
      }
    }

    moveRight();
  </script>
</body>
</html>

Этот пример демонстрирует цепочку анимаций, перемещая зелёный квадрат сначала вправо, а затем вниз. Функция moveRight перемещает квадрат вправо, пока он не достигнет края окна. Как только он достигает правого края, yPos явно сбрасывается в 0 перед вызовом moveDown. Такое последовательное выполнение в сочетании с правильным управлением состоянием для повторяющихся циклов показывает, как создавать более сложные последовательности анимаций, объединяя несколько анимаций.

Анимация нескольких свойств

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


html
<!DOCTYPE html>
<html>
<head>
  <style>
    #square {
      width: 50px;
      height: 50px;
      background-color: purple;
      position: absolute;
      left: 0;
      top: 0;
    }
  </style>
</head>
<body>
  <div id="square"></div>
  <script>
    const square = document.getElementById('square');
    let pos = 0;

    function changeColor(progress) {
      let red = Math.floor(255 * progress);
      let green = Math.floor(255 * (1 - progress));
      return `rgb(${red}, ${green}, 0)`;
    }

    function animate() {
      if (pos < window.innerWidth - 50) {
        pos += 2;
        let progress = pos / (window.innerWidth - 50);
        square.style.transform = 'translateX(' + pos + 'px)';
        square.style.backgroundColor = changeColor(progress);
        requestAnimationFrame(animate);
      }
    }

    animate();
  </script>
</body>
</html>

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

Оптимизация производительности JavaScript-анимаций

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

  1. Используйте requestAnimationFrame: этот метод синхронизируется с частотой обновления дисплея, обеспечивая более плавную анимацию.
  2. Минимизируйте манипуляции DOM: группируйте обновления DOM, чтобы уменьшить количество перерасчётов макета и перерисовок. Для изменения положения предпочитайте transform и opacity, чтобы использовать ускорение GPU.
  3. Оптимизируйте CSS: используйте CSS-свойства, ускоряемые GPU, такие как transform и opacity.
  4. Ограничивайте частоту событий: уменьшайте частоту событий, таких как resize или scroll, с помощью техник throttling или debouncing.
  5. Корректно останавливайте анимации: используйте cancelAnimationFrame, чтобы останавливать анимации, когда они больше не нужны. Сохраняйте идентификатор анимации и вызывайте cancelAnimationFrame(id), чтобы предотвратить утечки памяти. Пример:
    javascript
    let animationId = requestAnimationFrame(animate);
    // ... later ...
    cancelAnimationFrame(animationId);
  6. Избегайте дрожания макета: не считывайте свойства макета (например, offsetWidth, getBoundingClientRect) внутри цикла анимации, так как это заставляет браузер пересчитывать стили в середине кадра и может вызывать рывки.

INFO

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

Заключение

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

Практика

Какие методы и функции обычно используются в JavaScript-анимациях?

Считаете ли это полезным?

Предпросмотр dual-run — сравните с маршрутами Symfony на продакшене.