Chrome Dev Summit 2018 is happening now and streaming live on YouTube. Watch now.

Анимационные переходы между представлениями

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

TL;DR

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

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

Использование атрибутов translation для перемещения между представлениями

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

Переход между двумя представлениями

Чтобы достичь такого эффекта, вам потребуется контейнер для обоих представлений, которому будет задано свойство overflow: hidden. Таким образом, оба представления смогут находиться в контейнере одновременно без отображения горизонтальных полос прокрутки, при этом каждое представление будет при необходимости скользить из стороны в сторону внутри контейнера.

Иерархия представлений.

Код CSS для контейнера:

.container {
  width: 100%;
  height: 100%;
  overflow: hidden;
  position: relative;
}

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

.view {
  width: 100%;
  height: 100%;
  position: absolute;
  left: 0;
  top: 0;

  /* let the browser know we plan to animate
     each view in and out */
  will-change: transform;
}

Добавление transition к свойству transform обеспечивает привлекательный эффект скольжения. Чтобы скольжение вызывало приятные ощущения, необходимо использовать нестандартную кривую cubic-bezier, которая рассматривалась в документе [Руководство по изменению скорости при нестандартной анимации] (custom-easing.html).

.view {
  /* Prefixes are needed for Safari and other WebKit-based browsers */
  transition: -webkit-transform 0.3s cubic-bezier(0.465, 0.183, 0.153, 0.946);
  transition: transform 0.3s cubic-bezier(0.465, 0.183, 0.153, 0.946);
}

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

.details-view {
  -webkit-transform: translateX(100%);
  transform: translateX(100%);
}

Далее необходимо использовать небольшой фрагмент кода JavaScript для работы с классами. Это позволит включить соответствующие классы для представлений.

var container = document.querySelector('.container');
var backButton = document.querySelector('.back-button');
var listItems = document.querySelectorAll('.list-item');

/**
 * Toggles the class on the container so that
 * we choose the correct view.
 */
function onViewChange(evt) {
  container.classList.toggle('view-change');
}

// When you click on a list item bring on the details view.
for (var i = 0; i < listItems.length; i++) {
  listItems[i].addEventListener('click', onViewChange, false);
}

// And switch it back again when you click on the back button
backButton.addEventListener('click', onViewChange);

Наконец, добавляем декларации CSS для этих классов.

.view-change .list-view {
  -webkit-transform: translateX(-100%);
  transform: translateX(-100%);
}

.view-change .details-view {
  -webkit-transform: translateX(0);
  transform: translateX(0);
}

См. образец.

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

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

Обеспечение работы анимации на больших экранах

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

Иерархия представлений на большом экране.