Missed the action at this year's Chrome Dev Summit? Catch up with our playlist on YouTube. Watch now.

Сравнение анимации средствами CSS и JavaScript

В Интернете есть два основных способа создания анимации: с помощью CSS и JavaScript. Какой из них следует выбрать? Это зависит от других характеристик вашего проекта, а также от того, каких эффектов вы стремитесь добиться

TL;DR

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

Самую простую анимацию можно создавать как с помощью CSS, так и с помощью JavaScript, однако объем затрат труда и времени будет разным (см. также статью Производительность при использовании CSS и JavaScript – что лучше?). У каждого варианта есть свои достоинства и недостатки, но есть хорошие правила, которым нужно следовать:

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

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

Анимация с помощью CSS

Анимация с помощью CSS, без сомнения, является самым простым способом заставить что-то двигаться на экране.

Далее приведен код CSS, который перемещает элемент на 100 пикселей по осям X и Y. Делается это с помощью переходов CSS, для которых задано выполнение в течение 500 мс. При добавлении класса move значение свойства transform изменяется и начинается переход.

.box {
  -webkit-transform: translate(0, 0);
  -webkit-transition: -webkit-transform 500ms;

  transform: translate(0, 0);
  transition: transform 500ms;
}

.box.move {
  -webkit-transform: translate(100px, 100px);
  transform: translate(100px, 100px);
}

См. образец

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

Если, как в приведенном выше фрагменте, для управления анимацией создаются отдельные классы CSS, включать и выключать каждую анимацию можно будет с помощью JavaScript:

box.classList.add('move');

Это позволит достичь очень хорошей сбалансированности ваших приложений. Основное внимание можно уделить управлению состоянием с помощью JavaScript. В остальном же нужно просто задать соответствующие классы для целевых элементов, а анимацию при этом будет выполнять браузер. Если выбрать этот путь, то можно будет принимать события transitionend для элемента. Однако это не подходит для старых версий Internet Explorer; версия 10 была первой, в которой эти события стали поддерживаться. Все остальные браузеры поддерживают это событие довольно давно.

Код JavaScript, который требуется для приема события окончания перехода, выглядит следующим образом:

var box = document.querySelector('.box');
box.addEventListener('transitionend', onTransitionEnd, false);

function onTransitionEnd() {
  // Handle the transition finishing.
}

Помимо использования переходов CSS, также можно использовать анимацию CSS, которая позволяет намного точнее контролировать отдельные ключевые кадры, продолжительность и проходы анимации.

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

/**
 * This is a simplified version without
 * vendor prefixes. With them included
 * (which you will need) things get far
 * more verbose!
 */
.box {
  /* Choose the animation */
  animation-name: movingBox;

  /* The animation’s duration */
  animation-duration: 1300ms;

  /* The number of times we want
      the animation to run */
  animation-iteration-count: infinite;

  /* Causes the animation to reverse
      on every odd iteration */
  animation-direction: alternate;
}

@keyframes movingBox {
  0% {
    transform: translate(0, 0);
    opacity: 0.3;
  }

  25% {
    opacity: 0.9;
  }

  50% {
    transform: translate(100px, 100px);
    opacity: 0.2;
  }

  100% {
    transform: translate(30px, 30px);
    opacity: 0.8;
  }
}

См. образец

При создании анимации средствами CSS вы определяете саму анимацию независимо от целевого элемента, после чего требуемая анимация выбирается с помощью свойства animation-name.

Анимация с помощью CSS все еще сильно зависит от браузера, пр том что для ее обозначения в Chrome, Safari, Opera, Safari Mobile и Android Browser используется префикс -webkit-. В Internet Explorer и Firefox префиксы не используются. Есть много средств, позволяющих создавать требуемые версии CSS с префиксами, при этом версию без префикса можно написать в исходных файлах.

Анимация с помощью JavaScript

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

Далее приведен код JavaScript, который необходимо написать, чтобы воссоздать переход CSS, рассмотренный нами ранее.

function Box () {

  var animationStartTime = 0;
  var animationDuration = 500;
  var target = document.querySelector('.box');

  this.startAnimation = function() {
    animationStartTime = Date.now();
    requestAnimationFrame(update);
  };

  function update() {
    var currentTime = Date.now();
    var positionInAnimation = (currentTime - animationStartTime) / animationDuration;

    var xPosition = positionInAnimation * 100;
    var yPosition = positionInAnimation * 100;

    target.style.transform = 'translate(' + xPosition + 'px, ' + yPosition + 'px)';

    if (positionInAnimation <= 1)
      requestAnimationFrame(update);
  }
}

var box = new Box();
box.startAnimation();

См. образец

Этот код становится очень сложным и плохо управляемым, если попытаться охватить им несколько случаев, поэтому в целом рекомендуется выбрать одну из множества имеющихся библиотек JavaScript для анимации. Если вы уже используете jQuery в своем проекте, то вам, скорее всего, не следует переходить на другие варианты. Пользуйтесь функциями .animate(). Если же вам требуется специализированная библиотека, то попробуйте исключительно мощное средство TweenMax от Greensock. Существует его упрощенная версия под названием TweenLite, которая создает файлы не такого большого размера.

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