Анимация листа со спрайтами посредством steps()

http://simurai.com/post/37075268994/steps-animation
  • Перевод
  • Tutorial
[иллюстрация принципа]

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

у анимаций CSS с ключевыми кадрами есть свойство под названием animation-timing-function. Одна из его возможностей — использовать функцию steps(), как в нижеследующем примере:

div {
    animation: play 1s steps(10) infinite;
}
@keyframes play { 
      0% { background-position:    0px 0; } 
    100% { background-position: -500px 0; }
}

Различие между нею и остальными анимационными функциями состоит в том, что вместо плавного движения от 0px к −500px происходят резкие прыжки с паузами между ними. Это идеально подходит для анимаций, использующих лист с покадровым изображением спрайта. В вышеприведённом примере шаг равен 50px, а пауза — 100 миллисекунд (всего 10 шагов).

Вот небольшое демо.

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

Постскриптум.  Найден реальный пример употребления этого приёма: логотип Impending.
Поделиться публикацией

Комментарии 25

    +5
    Логотип Impending — крутая штука: PNG 6370×130 пикселов, почти полсотни кадров. Занимает 263 513 байтов.
      0
      Ого, КАК они его так сжали? Насколько я знаю, всякие там PNGcrush'и не дают такого хорошего результата
        +1
        Это тот случай когда надо пробовать. Пнг жмется хорошо, иногда удивительно хорошо. Я всегда сначала сохраняю в пнг и только потом перебираю остальные варианты.
        Хотя если бы ко мне пришли с просьбой анимировать картинку в 6к я бы сначала дал в глаз, а потом разбирался.
          +2
          imgo сжал этот файл до 250 254 байт
          +1
            0
            Этот пример не работает в Опере почему-то.
              0
              Потому, что соответствующий фрагмент CSS-кода в файле http://impending.com/wp-content/themes/impending/style.css выглядит вот так:

              #logoanim {
              	background: url("images/meteor.png") 0px 0px no-repeat;
              	width: 130px;
              	height: 130px;
              	position: absolute;
              	left: 666px;
              	top: 37px;
              	-webkit-animation: logoAnim 2s steps(47, end) infinite;
              	-moz-animation: logoAnim 2s steps(47, end) infinite;
              	-ms-animation: logoAnim 2s steps(47, end) infinite;
              }
              

              Нетрудно видеть, что с префиксами «-webkit-», «-moz-» и «-ms-» код «animation» способен работать только в WebKit (Apple Safari, Google Chrome), в Mozilla Firefox и в Microsoft Internet Explorer соответственно.

              Про браузер Opera позабыли.

              Впрочем, не так уж это и удивительно. По сведениям caniuse.com, поддержка «-o-animation» появилась в предпоследней версии (Opera 12), а поддержка «animation» — в последней (Opera 12.1). Возможно, создатели Impending просто не успели учесть это.

              (Хотя это не извиняет разработчика, воздержавшегося от записи безпрефиксной версии «animation» после браузеропрефиксных версий.)
            0
            Автор первоисточника пишет “the only problem is that it always starts from the beginning and makes it look jumpy”, но я не вижу, каким образом это проблема. Закольцовывать, закольцовывать надо — чтобы после последнего кадра анимации невозбранно мог идти первый кадр её.
              +2
              В статье эта фраза используется в контексте изменения скорости анимации. И от перезапуска анимации в момент смены частоты кадров никак не поможет закольцовывание.
                +1
                Ах вот оно что.
                +1
                У того же Impending заметны прыжки. Неужели они не догадались закольцевать?
                +1
                Я также часто использую keyframes для спрайтовой анимации. Однажды мне нужна была «скриптовая» динамика, и вот скрипт для динамичного создания keyframes-правил и старта анимации: github. Там правда используется timing-function: step-start для «прыжков» по кадрам.
                PS: работа с cssRules относительно дорогая процедура, поэтому нужно создавать подобные правила по-минимуму и кешировать их.
                  0
                  Ах, и забыл уточнить про закольцованость — проблема в первом и последнем фрайме — между ними нету интервала, поэтому происходит как бы «ускорение» в этом месте. Используя step-start надо оставлять «0%» пустым и стартовать с 100/ frameCount.
                  +3
                  Если сделать зум, то картинка «едет».
                    0
                    Возможно, это зависит от браузера.

                    (Я пробовал «делать зум» в Firefox 18; картинка либо не «едет», либо термин «едет» для меня означает некоторое другое понятие.)
                      0
                      Google Chrome 23.0.1271.95 m

                      При зуме размер картинки увеличивается, а шаг анимации остается прежним. Как результат — при малом увеличении видно, как картинка «проезжает» через рамку, при больших зумах — в рамке непонятно что.

                      Любопытно, что если нажать «обновить», то анимация «приспособится» к текущей величине зума и уже перестанет работать на стандартном масштабе.
                        0
                        Можно предполагать, что Вы только что обнаружили баг в Хроме и поэтому Вам следует сообщить о нём производителю.
                          0
                          Практика показывает, что багрепорты никогда не попадают разработчикам через техподдержку. Не знаю, как в гугле, а в российских компаниях на багрепорты отвечают предложением почистить кэш и перезагрузить компьютер. Ах да, еще требуют скриншоты, причем никогда не читают историю переписки (то есть если прислать скриншот, то запросят описание выполненных действий, а потом снова скриншот). Так что писать багрепорты без багтрекера меня отучили полностью.

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

                                Если же у Вас остаются сомнения о том, насколько этот эффект вызван вебкитом, а насколько конкретным скриптом, то тогда можете ведь самостоятельно изготовить тестовую страницу вообще без скриптов (только HTML, в котором картинка с кадрами анимации и CSS с описанием анимации), и проверить её поведение, и тем невозбранно узнать желаемое.

                                Именно тогда Вам станет ясно, что следует делать.
                    0
                    Google Chrome 23.0.1271.95 m

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

                    Очень похоже, что номер текущего кадра в недрах браузера вычисляется как floor((current_time() — start_time) * steps / duration) % steps, причем при изменении duration переменная start_time не меняется.
                      0
                      Вот небольшое демо.
                      Мне сперва показали нормальную анимацию, а потом её спрятали и сказали, что мой браузер не поддерживается. У меня FF 17.0.1.
                        0
                        У меня Firefox 18 (то есть бета-версия), анимация не прячется.
                        –1
                        Нечто похожие есть тут:
                        eu.battle.net/wow/ru/item/46140
                        В правом углу имеется возможность двигать предмет. Псевдо 3Д

                        Ну и сам клипарт media.blizzard.com/wow/renders/items/item46140.jpg

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое