CSS анимация: свойство transition. Слоистая анимация

CSS анимация: свойство transition. Слоистая анимация

От автора: CSS анимация и в частности свойство transition – отличный способ плавно передвинуть объект из точки А в точку В. Все это хорошо работает, если вы двигаете предмет по прямой. Не важно, сколько раз вы согнете кривые Безье, у вас не получится заставить двигаться объект по кривой линии при помощи свойств animation и transition. Можно ошибиться с временной функцией, что приведет к эффекту пружины, движения относительно осей Х и У всегда будут одинаковыми.

Тем не менее, есть более легкий способ для создания такой натуральной анимации без помощи JavaScript – слоистая анимация. Используя два или более объекта для анимации, можно контролировать любой участок пути. Одну тайминг функцию можно применить к движению по оси Х, другую – к движению по оси У.

Проблема

Перед тем как мы перейдем к решению, давайте поближе рассмотрим проблему. CSS свойства animation и transition ограничивают нас движением только по прямой. Как это происходит? Всегда выбирается кратчайший путь от точки А до точки В. Отлично же – в большинстве случаев этого достаточно – однако мы не можем сказать CSS пройтись «красивым путем», а не «самым коротким».

Самый простой способ в CSS анимации от одной точки к другой (с аппаратным ускорением) это свойство transform со значением translate. Таким образом можно получить движение вдоль прямой. В @keyframes блоке ниже мы движемся вверх и вниз из точки (0, 0) в точку (100, -100), как в примере выше:

@keyframes straightLine {
  50% {
    transform: translate3D(100px, -100px, 0);
  }
}

.dot {
  animation: straightLine 2.5s infinite linear;
}

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

В 0% объект находится в точке (0, 0), на 50% мы используем translate3D(100px, -100px, 0) для перемещения в точку (100, -100), затем перемещаемся обратно. Перефразируя, мы двигаем объект на 100px вправо и затем на 100px вверх. Два перехода вместе двигают объект в верхний угол.

Решение: одна функция на ось

Так как же создать движение по кривой, как показано выше? Чтобы объект двигался не по прямой линии необходимо, чтобы скорость передвижения по осям Х и У была разной.

В предыдущих примерах везде использовалась функция linear, однако если обернуть наш объект в контейнер, то одну функцию можно применить для передвижения по Х, а другую для передвижения по У. Ниже мы используем ease-in для оси Х и ease-out для У:

Реализация: один объект на ось

К сожалению, мы не можем задать несколько свойств transform, применено будет только последнее. Так как же на самом деле совместить две анимации? Мы поместим один объект внутрь другого и запустим одну анимацию для контейнера, а другую для дочернего элемента.

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

Точка располагается внутри бокса и двигается вместе с ним по оси Х, в то время как сама точка перемещается по оси У. Если убрать рамку контейнера, то мы получим передвижение по кривой. Вместо использования двух объектов в HTML можно добавить псевдокласс. Если HTML выглядит так:

<div class="dot"></div>

Можно добавить псевдокласс:

.dot {
  /* Контейнер. Перемещается по оси X */
}

.dot::after {
  /* Отрисовывает точку и перемещает ее вдоль оси У */
}

Нам нужно два отдельных блока анимации: один для оси Х, другой для У. Обратите внимание, как в первом блоке используется ease-in, а во втором ease-out:

.dot {
  /* тут идет код… */
  animation: xAxis 2.5s infinite ease-in;
}

.dot::after {
  /* Точка */
  animation: yAxis 2.5s infinite ease-out;
}

@keyframes xAxis {
  50% {
    animation-timing-function: ease-in;
    transform: translateX(100px);
  }
}

@keyframes yAxis {
  50% {
    animation-timing-function: ease-out;
    transform: translateY(-100px);
  }
}

Добавим вендорные префиксы для WebKit браузеров и парочку кривых Безье вместо ease-in и ease-out, и у нас получится пример, показанный в начале статьи:

.demo-dot {
  -webkit-animation: xAxis 2.5s infinite cubic-bezier(0.02, 0.01, 0.21, 1);
  animation: xAxis 2.5s infinite cubic-bezier(0.02, 0.01, 0.21, 1);
}

.demo-dot::after {
  content: '';
  display: block;
  width: 20px;
  height: 20px;
  border-radius: 20px;
  background-color: #fff;
  -webkit-animation: yAxis 2.5s infinite cubic-bezier(0.3, 0.27, 0.07, 1.64);
  animation: yAxis 2.5s infinite cubic-bezier(0.3, 0.27, 0.07, 1.64);
}

@-webkit-keyframes yAxis {
  50% {
    -webkit-animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1);
    animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1);
    -webkit-transform: translateY(-100px);
    transform: translateY(-100px);
  }
}

@keyframes yAxis {
  50% {
    -webkit-animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1);
    animation-timing-function: cubic-bezier(0.02, 0.01, 0.21, 1);
    -webkit-transform: translateY(-100px);
    transform: translateY(-100px);
  }
}

@-webkit-keyframes xAxis {
  50% {
    -webkit-animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64);
    animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64);
    -webkit-transform: translateX(100px);
    transform: translateX(100px);
  }
}

@keyframes xAxis {
  50% {
    -webkit-animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64);
    animation-timing-function: cubic-bezier(0.3, 0.27, 0.07, 1.64);
    -webkit-transform: translateX(100px);
    transform: translateX(100px);
  }
}

Код приведет нас к тому, с чего мы начали.

Вы, должно быть, уже заметили, что во всех примерах мы использовали @keyframes анимацию. Однако это только потому, что нам нужно было двигать точку назад и вперед. Если необходимо передвинуть объект из точки А в точку В, слоистая анимация хорошо работает со свойством transition.

Если объект спозиционирован абсолютно, анимировать по кривой линии его можно при помощи свойств left и bottom. В таком случае вам понадобится только один объект, контейнер добавлять не надо. Тем не менее, есть причина, по которой следует избегать такой анимации: производительность такой анимации очень низкая, и она отрисовывается на каждом кадре заново. Слоистая же анимация с псевдоклассами и аппаратным ускорением свойства translate делает передвижение очень плавным, не снижая производительность.

Автор: Tobias

Источник: http://tobiasahlin.com/

Редакция: Команда webformyself.

Практика HTML5 и CSS3 с нуля до результата!

Получите бесплатный пошаговый видеокурс по основам адаптивной верстки с полного нуля на HTML5 и CSS3

Получить

Метки:

Комментарии Вконтакте:

Комментарии Facebook:

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Я не робот.

Spam Protection by WP-SpamFree