Яндекс.Метрика

Дизайн-журнал №1. Актуальная информация для дизайнеров, веб дизайнеров, программистов и разработчиков сайтов.

Мастеркласс по CSS анимации

20 сентября 2011 | Опубликовано в css | 4 Комментариев »

Дежурка настоятельно рекомендует обратить внимание на следующую статью веб-разработчика, консультанта Эстель Уейл, в которой она расскажет вам все, что нужно знать для быстрого старта и полноценного использования замечательной технологии CSS3 анимации: от основ ключевых кадров до полезных советов по созданию анимации, которые сберегут вам много времени и нервов. 

«Анимация» в CSS всегда сводилась к hover-эффектам. С помощью псевдоклассов :hover и :focus мы могли изменять цвет, размер и положение элемента, цвет фона и другие свойства CSS, основываясь на действиях пользователя. Используя :hover, вы получаете всего два положения: с наведенным курсором и с ненаведенным, иначе говоря, только два ключевых кадра: начальный и конечный, никаких промежуточных состояний межу этими положениями, и, как результат, резкий и внезапный переход между ними. По сути дела, это никакая не анимация.

Переходы CSS3 transitions решили задачу промежуточных состояний, позволив переходить из ненаведенного состояния к наведенному в течение определенного промежутка времени. Transitions с вендорными префиксами отлично поддерживаются современными браузерами (начиная с IE10 и Firefox 4.0). Используя transitions, можно создавать простые анимации, ограниченные двумя ключевыми кадрами — начальной и конечной точками — и единичным повтором. Большинство разработчиков преодолевают эти ограничения, применяя для анимации JavaScript. С тех пор, как ситуация с поддержкой анимаций CSS3 браузерами улучшилась, пришла пора меньше полагаться на JavaScript и создавать анимацию уже непосредственно в CSS.

В этой статье вы научитесь всему, что нужно для создания анимации средствами CSS. Обращаю ваше внимание, что вам нужно будет использовать префиксы -webkit- и -moz-, для поддержки вашей анимации Chrome, Safari 4+, Firefox 5+, Android Chrome, и iOS.

Ключевые кадры

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

    @keyframes flapping {
    from {
    background-size: 100px 100px;
    }
    to {
    background-size: 20px 100px;
    }
    }

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

В этой анимации мы использовали условия from и to. Мы также можем использовать проценты, что обычно и требуется.

    @keyframes flapping {
    0% {
    background-size: 100px 100px;
    }
    100% {
    background-size: 20px 100px;
    }
    }

Объявляя анимации, необходимо помнить о следующем:

  • Не забывайте ставить знак %
    Когда речь идет о длинне, неважно, указанной в пикселях или em, 0 это 0. Но не при определении анимации. Не забывайте добавлять знак % при указании единиц измерения.
  • Не забывайте указывать 100%, либо объявлять финальный ключевой кадр анимации.
    Хотя спецификация и не требует обязательного указания 0% и 100%, однако это необходимо для сегодняшних браузеров.
  • Не берите имя анимации в кавычки
    Хотя, казалось бы, код становится разборчивей, когда вы берете имя в кавычки, однако это будет неверно относительно спецификации W3C и приведет к неработоспособности анимации в Firefox.

Одно из свойств, благодаря которым animation выигрывает перед transition — это возможность детально контролировать анимацию. К примеру, эта «радужная» анимация состоит из 11 блоков ключевых кадров.

    @keyframes rainbow {
    0% {background-color: #FF0000;}
    10% {background-color: #FF8000;}
    20% {background-color: #FFFF00;}
    30% {background-color: #80FF00;}
    40% {background-color: #00FF00;}
    50% {background-color: #00FF80;}
    60% {background-color: #00FFFF;}
    70% {background-color: #0080FF;}
    80% {background-color: #0000FF;}
    90% {background-color: #8000FF;}
    100% {background-color: #FF0080;}
    }

Если бы мы использовали здесь transition, переходя от начального #FF0000 к конечному #FF0080, мы бы просто получили переход от красного к розовому, пройдя только через оттенки красного. Благодаря же поэтапному контролю animation, мы получили тот же самый переход, но через все цвета спектра.

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

    @keyframes rainbowdimmer {
    0% {background-color: #FF0000; opacity: 1;}
    20% {background-color: #FFFF00;}
    40% {background-color: #00FF00;}
    50% {opacity: 0;}
    60% {background-color: #00FFFF;}
    80% {background-color: #0000FF;}
    100% {background-color: #FF0080; opacity: 1;}
    }

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

Заметьте также, что дублирование селекторов ключевых кадров не поддерживается:

    <s>100% {background-color: #FF0080;}</s>
    100% {opacity: 1;}

Если у двух блоков одинаковые селекторы, последующий блок отменяет действие предыдущих.

С другой сторны, если в вашей анимации содержатся дублирующиеся ключевые кадры, вам не придется объявлять один и тот же блок дважды. Вместо этого перечислите селекторы одинаковых ключевых кадров, разделив их запятыми. Порядок объявления не имеет значения (100% может стоять перед 0%).
В следующем примере с бабочкой начальное и финальное ее положение одинаковы. Вместо того, чтобы объявлять два отдельных блока, мы рразмещаем первый и последний селекторы через запятую:

    @keyframes movement {
    0%, 100% {
    top: 0;
    left: 0;
    }
    25% {
    top: 0;
    left: 100px;
    }
    50% {
    top: 100px;
    left: 100px;
    }
    75% {
    top: 100px;
    left: 0;
    }
    }

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

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

    @-webkit-keyframes bouncing {
    40%, 70%, 90%{
    animation-timing-function: ease-out;
    bottom: 0;
    }
    0% {
    bottom: 200px;
    left: 0;
    animation-timing-function: ease-in;
    }
    55% {
    bottom: 50px;
    animation-timing-function: ease-in;
    }
    80% {
    bottom: 25px;
    animation-timing-function: ease-in;
    }
    95% {
    bottom: 10px;
    animation-timing-function: ease-in;
    }
    100% {
    left: 110px;
    bottom: 0;
    animation-timing-function: ease-out;
    }
    }

Обратите внимание, что мы анимировали два свойства. Мы перемещали мячик вверх-вниз несколько раз, используя поэтапный контроль. Однако при этом движение слева направо было плавным, и, следовательно, тербовало объявление лишь двух ключевых кадров. Мы также изменяли animation-timing-function, чтобы подпрыгивание выглядело плавным и естественным. Мы еще вернемся к обсуждению animation-timing-function, а сейчас главное запомните, что animation-timing-function — это единственное свойство анимации, которое может быть включено в описание ключевого кадра. W3C предлагает незавершенный перечень свойств, котороые могут быть анимированны. Мы можем применять animation-timing-function, чтобы указать, как анимаци следует переходить к следующему ключевому кадру. Без этого наш мячик был слишком уж прыгучим.

Вендорные префиксы

Все эти анимации, однако, не везде будут работать. На момент написания статьи единственные браузеры, поддерживающие такую анимацию, требуют указания вендорных префиксов. Нам придется объявить @keyframes трижды: с префиксом -moz- для Firefox 5+, с префиксом -webkit- для Safari, Chrome и различных браузеров мобильных устройств и, наконец, без всякого префикса для браузеров, поддеживающих вендорно-нейтральный синтаксис.

    /* для браузеров Webkit */
    @-webkit-keyframes flitter {
    0%{
    -webkit-transform: scale(1,1);
    }
    100% {
    -webkit-transform: scale(0.2,1);
    }
    }
    /* для Firefox */
    @-moz-keyframes flitter {
    0%{
    -moz-transform: scale(1,1);
    }
    100% {
    -moz-transform: scale(0.2,1);
    }
    }
    /* Задел на будущее: для браузеров, поддеживающих безвендорный синтаксис */
    @keyframes flitter {
    0%{
    transform: scale(1,1);
    }
    100% {
    transform: scale(0.2,1);
    }
    }

В данном примере мы добавили вендорные префиксы к 'keyframes', а также к свойству transform, так как безвендорные трансформации все еще не поддерживаются.

Анимирование элементов

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

Давайте начнем с нашей бабочки.

    .butterfly {
    height: 100px;
    width: 100px;
    position: absolute;
    top: 50px; left: 50px;
    background-image: url(butterfly.png);
    }

Имя и продожительность анимации

Нашей первой целью будет заставить бабочку махать крыльями. Чтобы применить анимацию, мы указываем для элемента имя используемой анимации И ее продолжительность. Для этого у нас есть два свойства: animation-name и animation-duration. В свойстве animation-name можно указать список имен анимаций, разделенных запятыми, без кавычек.Это ваши имена, заданные в правиле @keyframes. Так, исходя из наших примеров, мы можем использовать хлопание и махание крыльями, радужные переливы и переливы с изменением прозрачности, а также подпрыгивание.

Кроме указания имени анимации, нам необходимо указать, как долго будет анимация длится, в секундах (s) или милисекундах (ms). Указав в свойстве animation-duration продожительность анимации, мы заставим анимацию повотряться от 0% до 100%. Минимальная продожительность — 1 милисекунда. В нашем первом примере с хлопающими крыльями мы брали значение 500ms, или 0,5s

    .butterfly {
    -webkit-animation-name: flitter;
    -webkit-animation-duration: 500ms;
    -moz-animation-name: flitter;
    -moz-animation-duration: 500ms;
    animation-name: flitter;
    animation-duration: 500ms;
    }

Счетчик повторов animation-iteration-count

Наша бабочка не машет крыльями (и даже не хлопает)? По умолчанию, анимация повторяется однократно. Для того же, чтобы запустить ее несколько раз, мы добавляем свойство animation-iteration-count. Его допустимым значением может быть либо целое число, либо ‘infinite’ — бесконечно. По умолчанию значение равно 1.

    .butterfly {
    -webkit-animation-name: flitter;
    -webkit-animation-duration: 500ms;
    -webkit-animation-iteration-count: infinite;
    -moz-animation-name: flitter;
    -moz-animation-duration: 500ms;
    -moz-animation-iteration-count: infinite;
    animation-name: flitter;
    animation-duration: 500ms;
    animation-iteration-count: infinite;
    }

Направление анимации animation-direction

Предыдущая анимация раздражает даже не столько тем, что не прекращается, но и тем, что переходит от своего 0% кадра к 100% за 500 милисекунд, а затем перепрыгивает снова на 0%. Получается, что в течение некоторого времени она изменяет ширину от 100px до 20px, а затем снова резко расширяется до 100% при переходе к следующему повтору.

Иногда нужно, чтобы анимации вели себя подобно переходам transition, когда при наведении курсора анимация проигрывается назад.
С помощью свойства animation-direction каждую последующую анимацию можно заставить проигрываться от 100% к 0%, то есть в обратную сторону. Прыгающий мячик двигается в одном и том де направлении, от 0% до 100%, а вот машущая крыльями бабочка как раз подходит в качестве примера для демонстрации изменения направления анимации. Давайте добавим это свойство нашей бабочке:

    .butterfly {
    -webkit-animation-name: flitter;
    -webkit-animation-duration: 500ms;
    -webkit-animation-iteration-count: 40;
    -webkit-animation-direction: alternate;
    -moz-animation-name: flitter;
    -moz-animation-duration: 500ms;
    -moz-animation-iteration-count: 40;
    -moz-animation-direction: alternate;
    animation-name: flitter;
    animation-duration: 500ms;
    animation-iteration-count: 40;
    animation-direction: alternate;
    }

Ускорение и замедление 'animation-timing-function'

Мы можем еще лучше настроить нашу анимацию, указывая в animation-timing-function, как значения должны просчитываться с течением времени. Значение по умолчанию — 'ease' (замедляться), но большинство движений в живой природе то замедляются, то ускоряются. Давайте добавим значение ease-in-out нашей animation-timing-function.

    .butterfly {
    -webkit-animation-name: flitter;
    -webkit-animation-duration: 500ms;
    -webkit-animation-iteration-count: 40;
    -webkit-animation-direction: alternate;
    -webkit-animation-timing-function: ease-in-out;
    -moz-animation-name: flitter;
    -moz-animation-duration: 500ms;
    -moz-animation-iteration-count: 40;
    -moz-animation-direction: alternate;
    -moz-animation-timing-function: ease-in-out;
    animation-name: flitter;
    animation-duration: 500ms;
    animation-iteration-count: 40;
    animation-direction: alternate;
    animation-timing-function: ease-in-out
    }

Мы уже добавляли ease-in и ease-out на разных этапах, анимируя подпрыгивающий мячик. Повторим, что animation-timing-function — это единственное свойство анимации, которое может быть включено в описание ключевого кадра. Используйте animation-timing-function, чтобы указать, как анимации следует переходить к следующему ключевому кадру. Без этого наш мячик был бы чересчур прыгучим.

Задержка ‘animation-delay’

По умолчанию, анмация начитается немедленно помле применения. Это можно изменять с помощью свойства animation-delay. Хоть на первый взгляд это очень просто, тут есть небольшая хитрость, о которой стоит знать. Если вам необходимо, чтобы анимация началась c середины, укажите отрицательное значение animation-delay. Например, если 10-секундной анимации указать значение задержки -5s, ваша анимация начнется немедленно, но с середины.

‘animation’ (краткая запись)

Свойства анимаций подробны и многословны. Даже чересчур. Особенно с вендорными префиксами. К счастью, существует краткая запись. Она должна включать имя и продолжительность анимации. Если вы указываете задержку, укажите ее первой. Вот общий порядок записи:

    animation: <name> <duration> <timing -function> <delay> <iteration -count>
        <direction> <fill -mode>;

Таким образом, мы можем записать предыдущую анимацию намного проще:

    .butterfly {
    -webkit-animation: flitter 500ms ease-in-out 5s 40 alternate;
    -moz-animation: flitter 500ms ease-in-out 5s 40 alternate;
    animation: flitter 500ms ease-in-out 5s 40 alternate;
    }

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

    .butterfly {
    -webkit-animation: flitter 300ms ease-in-out 1s 40 alternate, movement 5s linear 2s;
    -moz-animation: flitter 300ms ease-in-out 1s 40 alternate, movement 5s linear 2s;
    animation: flitter 300ms ease-in-out 1s 40 alternate, movement 5s linear 2s;
    }

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

    .butterfly {
    -webkit-transform-origin:-20px -20px;
    -moz-transform-origin:-20px -20px;
    -webkit-animation:
    flitter 300ms ease-in-out 1s 40 alternate,
    bouncing 10s ease-in-out 1s,
    rotation 0.5s ease 24 1s;
    -moz-animation:
    flitter 300ms ease-in-out 1s 40 alternate,
    bouncing 10s ease-in-out 1s,
    rotation 0.5s ease 24 1s;
    animation:
    flitter 300ms ease-in-out 1s 40 alternate,
    bouncing 10s ease-in-out 1s,
    rotation 0.5s ease 24 1s;
    }

Мы добавили transform-origin, чтобы вращение выглядело более случайным и естественным. Также обратите внимание, что у нас три анимации, которые оканчиваются на 13, 11 и 13 секундах соответственно. Добавляя несколько анимаций, соотносите сроки их действия между собой.

Animation-fill-mode

Наша бабочка чудесно порхает по странице, но судорожно дергается в верхний левый угол, когда завершается «подпрыгивающая» анимация. Благодаря свойству animation-fill-mode мы можем попросить бабочку оставаться в нижнем правом углу, когда завершится анимация.

Аnimation-fill-mode может принимать одно из 4 значений: backwards, forwards, none или both. По умолчанию — none.

Значение backwards заставляет элемент двигаться после загрузки страницы к 0% кадру, даже если установлена задержка animation-delay, и оставаться там, пока не начнется анимация.

Значение forwards указывает браузеру, что следует остановить анимацию на последнем кадре по окончанию последнего повтора и не отматывать ее к первоначальному состтоянию.

Значение both включает в себя оба значения, оставаясь в первом ключевом кадре до старта анимации (невзирая на возможное позитивное значение задержки) и задерживаясь на последнем кадре до конца последней анимации. Как раз то, что нам нужно для нашего «подпрыгивания»:

    .butterfly {
    -webkit-transform-origin:-20px -20px;
    -moz-transform-origin:-20px -20px;
    -webkit-animation:
    flitter 300ms ease-in-out 1s 40 alternate,
    bouncing 10s ease-in-out 1s both,
    rotation 0.5s ease 24 1s forwards;
    -moz-animation:
    flitter 300ms ease-in-out 1s 40 alternate,
    bouncing 10s ease-in-out 1s both,
    rotation 0.5s ease 24 1s forwards;
    animation:
    flitter 300ms ease-in-out 1s 40 alternate,
    bouncing 10s ease-in-out 1s both,
    rotation 0.5s ease 24 1s forwards;
    }

Остановка и запуск анимации

В дополнение к остановкам анимации в первом и последнем кадрах мы можем оcтанавливать ее в процессе с помощью animation-play-state. По умолчанию, все анимации имеют значение 'running', но его можно изменить на 'paused':

    .butterfly:hover {
    -webkit-animation-play-state:paused;
    -moz-animation-play-state:paused;
    animation-play-state:paused;
    }

Чтобы увидеть, как это работает, просто наведите курсор на любую из анимированных ранее бабочек.

Мы с вами разобрали простую анимацию, исключительно с целью показать, что возможно. Эффективные CSS анимации предоставляют возможность анимирования без использования JavaScript. Важно, однако, не забывать, что возможность анимации не означает, что их использование всюду окажется хорошей идеей. Используйте анимации рассудительно. Мы бы не хотели вернуться к ситуации с анимированными gif в конце 90х или повальными Flash-заставками в начале 2000х

Помните: если вы можете, это еще не значит, что вам следует!

По материалам статьи Эстель Уейл 




Комментарии

  1. Teodot
    Thumb up Thumb down +7

    Спасибо! Очень полезная, а главное доходчиво написанная статья. Небольшой вопрос: возможно осуществить запуск CSS3-анимации при наведении «мышки» (т.е. до того как курсор не попадает в область блока с анимацией — она не происходит, а запускается лишь при нахождении курсора в этой области)? Или тут лучше пользоваться CSS3-transition?

  2. serken
    Thumb up Thumb down +2

    Действительно очень хорошо

    Не хватает только примеров с использованием :active

  3. Михаил
    Thumb up Thumb down 0

    Здравствуйте. Подскажите пожалуйста, как исправить код под Мозиллу? В Хроме и Опере нормально летает бабочка.

    ddx=0;ddy=0;PX=600;PY=0;xm=0;ym=0

    OlsW=Ols.width/2;OlsH=Ols.height/2

    function MoveWinnie (){

    x=Math.round (PX+=((xm-PX)*3)/400)

    y=Math.round (PY+=((ym-PY)*3)/400)

    Ols.style.left=x-OlsW

    Ols.style.top=y //osw

    setTimeout («MoveWinnie ()»,10)

    }

    function doMouse (){

    xm=window.event.x

    ym=window.event.y //fantasyflash.ru

    }

    document.onmousemove=doMouse

    MoveWinnie ()

    fantasyflash.ru/script/in...t=kursor&n=7

    Михаил Ответ:

    Thumb up Thumb down 0

    fantasyflash.ru/script/web/kursor7.php