Запуск кода после завершения анимации AngularJS

У меня есть элемент, видимость которого переключается с помощью ng-show. Я также использую анимацию CSS — автоматические из ng-animate — для этого элемента, чтобы оживить его запись.

Элемент будет содержать изображение или видео.

В случае, если элемент содержит видео, я хочу воспроизвести его, но не хочу воспроизводить видео, пока не завершится его анимация.

Поэтому мне было интересно, есть ли простой способ привязать обратный вызов к концу анимации CSS в AngularJS?

документы ссылаются на doneCallback, но я не вижу способа указать это...

Один обходной путь (?), о котором я подумал, - это $watching element.hasClass("ng-hide-add-active") и ожидание его запуска с (true, false), подразумевая, что он только что был удален.

Есть ли более приятный способ?


person Ed_    schedule 04.01.2014    source источник
comment
вы указываете количество секунд в анимации css, устанавливаете такое же количество в $ timeout?   -  person YOU    schedule 04.01.2014
comment
@YOU: Я мог бы сделать, но, на мой взгляд, это еще менее аккуратно - они полностью отделены друг от друга.   -  person Ed_    schedule 04.01.2014
comment
кстати, есть вопрос относительно обратных вызовов анимации css - stackoverflow.com/q/6186454, stackoverflow.com/q/9255279 , stackoverflow.com/q/2087510   -  person YOU    schedule 04.01.2014
comment
Спасибо, но этот вопрос больше касается angularjs, чем общей анимации css.   -  person Ed_    schedule 04.01.2014
comment
То, что вы видите в документах, предназначено для директив. И я настоятельно рекомендую реализовать его, так как это единственное чистое решение ИМХО.   -  person a better oliver    schedule 04.01.2014
comment
@zeroflagL Я вижу - элемент, который я анимирую, уже является директивой? Это то, что вы имели ввиду? Или я должен реализовать какую-то пользовательскую директиву анимации?   -  person Ed_    schedule 04.01.2014
comment
Вместо ng-show вы используете свою собственную директиву. Или, если он у вас уже есть, используйте его и для анимации и удалите ng-show.   -  person a better oliver    schedule 04.01.2014
comment
Спасибо, я посмотрю, как это сделать.   -  person Ed_    schedule 04.01.2014


Ответы (3)


Ответ @michael-charemza отлично сработал для меня. Если вы используете Angular 1.3, обещание немного изменилось. Я немного застрял на этом, но вот изменение, которое заставило его работать:

if (show) {
  $animate.removeClass(element, 'ng-hide').then(scope.afterShow);
}
if (!show) {
  $animate.addClass(element, 'ng-hide').then(scope.afterHide);
}

Планкер: Пример кода

person Lereveme    schedule 30.10.2014

Как предложил @zeroflagL, пользовательская директива для замены ngShow, вероятно, является подходящим способом. Вы можете использовать & для передачи обратных вызовов в директиву, которую можно вызвать после завершения анимации. Для согласованности анимация выполняется путем добавления и удаления класса ng-hide, который является тем же методом, что и обычная директива ngShow:

app.directive('myShow', function($animate) {
  return {
    scope: {
      'myShow': '=',
      'afterShow': '&',
      'afterHide': '&'
    },
    link: function(scope, element) {
      scope.$watch('myShow', function(show, oldShow) {
        if (show) {
          $animate.removeClass(element, 'ng-hide', scope.afterShow);
        }
        if (!show) {
          $animate.addClass(element, 'ng-hide', scope.afterHide);
        }
      });
    }
  }
})

Пример использования этого прослушивания переменной области видимости show будет таким:

<div my-show="show" after-hide="afterHide()" after-show="afterShow()">...</div>

Поскольку это добавление/удаление класса ng-hide, пункты об анимации из документов о ngShow по-прежнему действительны, и вам нужно добавить display: block !important в CSS.

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

person Michal Charemza    schedule 04.01.2014
comment
Я использую это на Plunker и отлично работает, однако, если я изменю angular на версию 1.3, обратный вызов больше не запускается. Похоже, что функции addClass и removeClass больше не принимают обратный вызов? - person L. Desjardins; 20.01.2015
comment
Неважно, похоже, вам нужно использовать .then(function() {}); для версии 1.3 - person L. Desjardins; 20.01.2015
comment
Кроме того, если вы собираетесь использовать анимацию css, не забудьте добавить {tempClasses: 'ng-hide-animate'} в качестве третьего аргумента после element и 'ng-hide' перед вызовом .then, как указано в комментарии выше. - person Matt Waldron; 22.09.2015

Решение @michal-charemza прекрасно работает, но директива создает изолированную область, поэтому в некоторых случаях она не может быть прямой заменой директивы ng-show по умолчанию.

Я немного изменил его, чтобы он не создавал новых областей видимости и мог использоваться взаимозаменяемо с директивой ng-show.

app.directive('myShow', function($animate) {
  return {
    link: function(scope, element, attrs) {
      scope.$watch(attrs['myShow'], function(show, oldShow) {
        if (show) {
          $animate.removeClass(element, 'ng-hide').then(function(){
            scope.$apply(attrs['myAfterShow']);
          });
        } else {
          $animate.addClass(element, 'ng-hide').then(function(){
            scope.$apply(attrs['myAfterHide']);
          });
        }
      });
    }
  }
})

Использование:

<div my-show="show" my-after-hide="afterHide()" my-after-show="afterShow()">...</div>

Plunker

person m.bemowski    schedule 16.01.2017