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

Не так давно мы делали сайт для инженерного центра ИКАР AIRBUS, который занимается разработками и исследованиями в области самолето- и машиностроения. Самолет — отличный образ для презентации на главной странице: тут и обозначение отрасли, и технологичность, и стремление вперед и вверх. И вот как раз это «вперед и вверх» мы решили визуализировать, используя возможности CSS3.

У нас было несколько идей, как это изобразить. И хотя в итоге на сайте сделано было по-другому, для разбора возможностей CSS-анимации будет интересно разобрать вот такой вариант:

Теперь расскажу, как мы это делали.

Кратко о CSS-анимации

Но сначала нужно сделать небольшое лирическое отступление. На сегодняшний день есть два способа анимации элементов веб-страницы с помощью CSS: transition и animation. Для начала давайте рассмотрим простой пример анимации.

Допустим, у нас есть поле ввода (input) шириной 100 px в неактивном состоянии. При фокусе нам нужно анимировать увеличение его ширины до 300 px. Пойдем длинным путем и сделаем это двумя способами: через transition и непосредственно через CSS-animation.

Для примера с transition сначала опишем просто два состояния: неактивное и состояние при фокусе на input.


input {
    width: 100px;
}
input:focus
    width: 300px;
}

Далее для плавности перехода (анимирования) от одного состояния у другому просто добавим правило transition: width .5s linear:


input {
    width: 100px;
    transition: width .5s linear;
}

Тот же пример, но уже с использованием CSS-animation:


input {
    width: 100px;
}
input:focus {
    animation: input-animation .5s ease forwards;
}
@keyframes input-animation {
    to {
        width: 300px;
    }
}

Как видите, используя свойство animation мы можем не только описать конечное состояние объекта анимации, но и задать промежуточные значения (перед завершением анимации ширина поля была 400 px).

See the Pen ncIDl by Nico_t (@nico_t) on CodePen.

А теперь давайте разберем синтаксис CSS-анимаций.

animation: animationName .5s linear 1s 1 alternate forwards

Animation-name. Название правила @keyframes, которое определяет список ключевых кадров анимации. Подробнее о нем ниже.

Animation-duration. Длительность анимации. Значение можно задавать как в секундах (2s) так и в миллисекундах (500ms).

Timing-function (опционально). Описывает, как будет меняться во времени анимация. По умолчанию разработчику доступны следующие значения linear, ease (дефолтное значение), ease-in, ease-in-out, ease-out, step-start, step-end, steps и cubic-bazier. Примеры значений можно посмотреть на http://matthewlein.com/ceaser/.

Steps. Используя данное значение, можно описать шаги анимации, указав два параметра для данной функции — например steps(3, start). Первый параметр определяет количество интервалов анимации, второй, необязательный параметр, определяет точку в интервале, где будут происходить изменения значений свойств. Второй параметр ограничен значениями start и end. Steps в основном используют для спрайтовых анимаций.

See the Pen HEbov by Nico_t (@nico_t) on CodePen.

Step-start. Если выбрать это значение, анимация сразу перейдет в конечное состояние и останется в таком положении до конца. Эквивалентно значению steps(1, start).

Step-end. Аналогично предыдущему значению, только все наоборот. Эквивалентно значению steps(1, end).

Cubic-bezier. Тайминг-функция, построенная на основе кривой Безье. Матчасть и генератор Безье. Можно смело сказать, что все значения тайминг-функций, кроме steps, есть не что иное как предопределенные значения функции cubic-bezier. Например, значение ease равно значению cubic-bezier(0.25, 0.1, 0.25, 1), ease-in-out равно cubic-bezier(0.42, 0, 0.58, 1) и т.д.

Animation-delay (опционально). Задержка перед началом анимации. Задается в секундах или миллисекундах.

Animation-iteration-count. Свойство, которое определяет, сколько раз будет воспроизводиться анимация (цикл анимации). Дефолтное значение равно единице (анимация будет воспроизведена один раз). Значение может быть задано числом (1, 4, 10, 2.4) или состоянием Infinite, при котором, как вы, наверное, уже догадались, анимация будет непрерывной.

Animation-direction. Направление анимации. Значения:

  • Normal. Анимация будет воспроизводиться только в прямом порядке.
  • Reverse. Противоположно предыдущему значению.
  • Alternate. Циклы анимации чередуются между воспроизведением в прямом (нечетные циклы — 1, 3, 5…) и обратном (четные циклы — 2, 4, 6…) направлениях.
  • Alternate-reverse. Как в предыдущем, только сначала четные циклы, потом нечетные.

See the Pen kmtao by Nico_t (@nico_t) on CodePen.

Animation-fill-mode. Свойство, которое определяет поведение анимации вне времени ее воспроизведения. Значения:

  • Normal. Значение по умолчанию.
  • Forward. Значение свойства (последнее свойство keyframes) сохраняется после окончания анимации.
  • Backward. Начальное значение свойства (как определено в первом keyframe) применяется до начала анимации в течение периода, указанного в animation-delay.
  • Both. Комбинация forward и backward.

Анимация слайдера на примере ИКАР

Переход между слайдами

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

Переход с второго слайда на третий.

Код в этом случае будет выглядеть таким образом:


.view {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    overflow: hidden;
}
.view .container {
    position: absolute;
    top: 0;
    left: 0;
    width: 1660px;
    height: 10000px;
    transition: transform 4s linear;
}
.container .slide-2 {
    top: 1350px;
    left: 700px;
}
.view.active .container{
    transform: translate(-700px, -1350px);
}

В данном примере вместо значений top и left мы использовали свойство transform: translate(x, y), где x — это значение свойства top, а y — значение left. Почему лучше использовать transform:translate(x, y), вы можете почитать здесь.

Движение самолета с плавной прорисовкой его траектории

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

Поворачивать самолет будем свойством transform: rotate(x). Для этого просто подберем угол поворота в соответстующей точке анимации. Имитацию взлета самолета мы будем делать с помощью свойства transform: scale(x), добавим его в keyframe.

Отрисовка траектории

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


@keyframes path-animation {
   0% {height: 0;}
   5% {height: 94px;}
   10% {height: 149px;}
   15% {height: 204px;}
   20% {height: 258px;}
   25% {height: 313px;}
   30% {height: 368px;}
   35% {height: 422px;}
   40% {height: 477px;}
   45% {height: 532px;}
   50% {height: 587px;}
   55% {height: 652px;}
   60% {height: 717px;}
   65% {height: 783px;}
   70% {height: 848px;}
   75% {height: 914px;}
   80% {height: 979px;}
   85% {height: 1045px;}
   90% {height: 1100px;}
   95% {height: 1100px;}
   100% {height: 1100px;}
}

Пример движения самолёта

Движение туч

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


@keyframes cloud-anim {
    0% {
        left: -140%;
    }

    100% {
        left: 10%;
    }
}

Тучи у нас будут двигаться з разной скоростью и с разной задержкой. Для этого каждой туче пропишем свое значение animation-delay и animation-duration.


div[class*="cloud-"] {
    animation-name: cloud-anim;
    animation-iteration-count: infinite;
}

.cloud-1 {
    animation-duration: 35s;
}

.cloud-2 {
    animation-duration: 35s;
    animation-delay: 5s;
}

Как видите, даже такие на первый взгляд сложные вещи можно достаточно несложно осуществить с помощью CSS3. Это открывает нам дорогу для новых сумасшедших идей, и все, что ограничивает нас теперь — только фантазия.