Улучшить эту документацию Просмотреть исходный код $animateCss
- сервис в модуле ngAnimate
Обзор
Сервис $animateCss — полезный инструмент для запуска настраиваемых CSS-переходов/ключевых кадров из JavaScript-анимации или непосредственно из директивы. Цель $animateCss — НЕ обойти механизмы работы $animate и ngAnimate, а предоставить возможность существующим анимациям или директивам создавать более сложные анимации, управляемые исключительно CSS-кодом.
Обратите внимание, что анимации, запускаемые через $animateCss, могут быть рендерены только браузерами, поддерживающими CSS-переходы и/или анимации ключевых кадров (плохие новости для IE9 и ниже).
Общее использование
Опять же, $animateCss предназначен для использования внутри зарегистрированной JavaScript-анимации, работающей с ngAnimate. Можно использовать $animateCss напрямую внутри директивы, однако, автоматическое управление отменением анимации и/или предотвращением запуска анимации дочерних элементов не будет обрабатываться AngularJS. Для корректной работы необходимо использовать $animate для запуска анимации и настроить JavaScript-анимацию, которая инжектирует $animateCss для запуска CSS-анимации.
В примере ниже показано, как создать анимацию сворачивания элемента с помощью ng-if:
<!-- notice the `fold-animation` CSS class --> <div ng-if="onOff" class="fold-animation"> This element will go BOOM </div> <button ng-click="onOff=true">Fold In</button>
Теперь создадим JavaScript-анимацию, которая запустит CSS-переход:
ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
return {
enter: function(element, doneFn) {
var height = element[0].offsetHeight;
return $animateCss(element, {
from: { height:'0px' },
to: { height:height + 'px' },
duration: 1 // one second
});
}
}
}]);
Более сложные применения
$animateCss — это базовый код, который ngAnimate использует для работы с CSS-анимациями за кулисами. Следовательно, такие CSS-фичи, как .ng-EVENT, .ng-EVENT-active, .ng-EVENT-stagger, могут быть активированы с помощью $animateCss через JavaScript-код.
Это также означает, что практически любая комбинация добавления классов, удаления классов, установки стилей, динамического задания анимации ключевых кадров, применения жестко заданного значения длительности или задержки, изменения плавности анимации или применения анимации с задержкой — всё это работает с $animateCss. Сам сервис достаточно умён, чтобы определить комбинацию опций и проанализировать свойства стилей элемента, обеспечивая работоспособную анимацию, которая будет выполнена с помощью CSS.
В примере ниже показана более сложная версия .fold-animation из предыдущего примера:
ngModule.animation('.fold-animation', ['$animateCss', function($animateCss) {
return {
enter: function(element, doneFn) {
var height = element[0].offsetHeight;
return $animateCss(element, {
addClass: 'red large-text pulse-twice',
easing: 'ease-out',
from: { height:'0px' },
to: { height:height + 'px' },
duration: 1 // one second
});
}
}
}]);
Поскольку мы добавляем/удаляем CSS-классы, то CSS-переход также их подхватит:
/* since a hardcoded duration value of 1 was provided in the JavaScript animation code,
the CSS classes below will be transitioned despite them being defined as regular CSS classes */
.red { background:red; }
.large-text { font-size:20px; }
/* we can also use a keyframe animation and $animateCss will make it work alongside the transition */
.pulse-twice {
animation: 0.5s pulse linear 2;
-webkit-animation: 0.5s pulse linear 2;
}
@keyframes pulse {
from { transform: scale(0.5); }
to { transform: scale(1.5); }
}
@-webkit-keyframes pulse {
from { -webkit-transform: scale(0.5); }
to { -webkit-transform: scale(1.5); }
}
Учитывая эту сложную комбинацию CSS-классов, стилей и опций, $animateCss всё рассчитает и запустит анимацию.
Как обрабатываются опции
$animateCss очень универсален и интеллектуален в определении конфигураций для элемента, чтобы анимация работала с заданными опциями. Например, если мы добавляем класс, содержащий значение ключевого кадра, и хотим также анимировать некоторые встроенные стили, используя свойства from и to.
var animator = $animateCss(element, {
from: { background:'red' },
to: { background:'blue' }
});
animator.start();
.rotating-animation {
animation:0.5s rotate linear;
-webkit-animation:0.5s rotate linear;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@-webkit-keyframes rotate {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}
Здесь отсутствуют переходы (в CSS-коде или в опциях $animateCss). Длительность анимации будет определяться из стилей ключевых кадров в CSS-классе, который добавляется. В этом случае $animateCss автоматически создаст встроенный стиль перехода, соответствующий длительности, определенной из стилей ключевых кадров (которые присутствуют в CSS-классе, который добавляется), и подготовит как переходы, так и анимации ключевых кадров для параллельного выполнения на элементе. Затем, во время анимации, заданные CSS-стили from и to будут применены и распределены по переходу и анимации ключевых кадров.
Что возвращается
$animateCss работает в две стадии: подготовка и анимация. Поэтому при первом вызове $animateCss анимация не запускается. Происходит только подготовка элемента к анимации (т.е. на элемент добавляются и удаляются сгенерированные CSS-классы). После вызова $animateCss возвращается объект со следующими свойствами:
var animator = $animateCss(element, { ... });
Теперь как выглядит содержимое нашей переменной animator:
{
// starts the animation
start: Function,
// ends (aborts) the animation
end: Function
}
Для запуска анимации необходимо выполнить animation.start(), которое вернёт промис, на котором можно отследить окончание анимации. Если мы не хотим запускать анимацию, то ДОЛЖНЫ выполнить animation.end() для очистки элемента (поскольку некоторые CSS-классы и стили могли быть применены к элементу на этапе подготовки). Обратите внимание, что все остальные свойства, такие как длительность, задержка, переходы и ключевые кадры, являются просто свойствами, и изменение их не переконфигурирует параметры анимации.
runner.done() vs runner.then()
Документировано, что animation.start() возвращает объект промиса, и это правда, однако, на объекте runner также доступен дополнительный метод .done(callbackFn). Метод done работает так же, как .finally(callbackFn), но не запускает переваривание (digest). Поэтому по соображениям производительности всегда лучше использовать runner.done(callback) вместо runner.then(), runner.catch() или runner.finally(), если вам действительно нужен запуск переваривания (digest) после.
Обратите внимание, что для упрощения ngAnimate изменил API JS-анимаций, чтобы распознавать, когда экземпляр runner возвращается из $animateCss (поэтому нет необходимости вызывать runner.done(doneFn) в вашем коде JavaScript-анимации). Проверьте код анимации выше по адресу animation code above, чтобы увидеть, как это работает.
Использование
$animateCss(element, options);
Аргументы
| Параметр | Тип | Подробности |
|---|---|---|
| element | DOMElement | элемент, который будет анимирован |
| options | object | опции, относящиеся к анимации, которые будут применены во время анимации
|
Возвращаемое значение
object |
объект с методами start и end и деталями об анимации.
|
© 2010–2018 Google, Inc.
Licensed under the Creative Commons Attribution License 4.0.
https://code.angularjs.org/1.6.9/docs/api/ngAnimate/service/$animateCss