Как событие прослушивания angular для перехода css может завершиться там, где ng-style запускает переход

#javascript #angularjs

#javascript #angularjs

Вопрос:

Мне пришлось добавить немного jQuery в конец кода, чтобы определить, когда заканчивается переход css. Есть ли способ заставить angular сделать это?

рабочий jsfiddle здесь

Способ, которым это работает, состоит в том, чтобы иметь объект, содержащий верхние и левые координаты, который вводится как встроенный стиль с помощью ng-style.

Некоторые из этих объектов хранятся в массиве. Всякий раз, когда обнаруживается событие перехода css3 end, вводится следующий объект.

Вот HTML с директивами Angular.

  <div id="mycontainer" ng-controller="mycontroller">
   <div ng-repeat="item in mylist" id="item{{item.key}}" class="item" ng-style="myproperties({{item.key}})">{{item.value}}</div>
 </div>
 <div id="readout"></div>
  

Вот Javascript / Angular, вы увидите jQuery, действительно явно добавленный ближе к концу.

 var myapp = angular.module('myapp', []);
myapp.controller(
  'mycontroller', 
  [
    '$scope',
    '$log',
    function($scope, $log) {
      // define the items
      $scope.mylist = [];
      for (var i = 0; i < 6; i  ) {
        $scope.mylist[i] = {'key':i, 'value':i, 'inlinestyle':{'top':'60px','left': (i*60) 'px'}};
      }

      $scope.myproperties = function(arg) {
              return $scope.mylist[arg].inlinestyle;
      };

      /*  test animatimng item number 2 */

      var anime = [
        {'top':'120px','left':'50px', 'background':'#ccc'},
        {'top':'150px','left':'120px', 'background':'#3cc'},
        {'top':'60px','left':'120px', 'background':'#c3c'},
        {'top':'120px','left':'130px', 'background':'#cc3'},
        {'top':'150px','left':'160px', 'background':'#fff'}
      ];
      var playhead = 0;
      var saveTimeStamp = 0;

      // adter a second, start the anime sequence
      setTimeout(function(){
        $scope.mylist[2].inlinestyle = anime[0];              
        $scope.$apply();
        playhead  ;       
      }, 1000);

      //listener for end of transition
      // aaaah ...  now I have to use jQuery
      $('html').on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function(e){
        if (( e.timeStamp != saveTimeStamp ) amp;amp; (anime[playhead])  )  {
          $('#readout').append('ended ' playhead ' ' JSON.stringify(anime[playhead]) '<br>');
          saveTimeStamp = e.timeStamp;            
          $scope.mylist[2].inlinestyle = anime[playhead];              
          $scope.$apply();
          playhead  ;
        }                
      });

    }
  ]
);
  

Ответ №1:

Угловой способ заключается в определении директивы.

Я следил за этим сообщением в блоге: https://jonsuh.com/blog/detect-the-end-of-css-animations-and-transitions-with-javascript / и преобразовал этот код в угловую директиву следующим образом:

  myapp.directive('myTransitionEnd', [
           '$parse',
 function ( $parse  ) {
    var transitions = {
        "transition"      : "transitionend",
        "OTransition"     : "oTransitionEnd",
        "MozTransition"   : "transitionend",
        "WebkitTransition": "webkitTransitionEnd"
    };

    var whichTransitionEvent = function () {
        var t,
            el = document.createElement("fakeelement");

        for (t in transitions) {
            if (el.style[t] !== undefined){
                return transitions[t];
            }
        }
    };

    var transitionEvent = whichTransitionEvent();

    return {
        'restrict': 'A',
        'link': function (scope, element, attrs) {
            var expr = attrs['myTransitionEnd'];
            var fn = $parse(expr);

            element.bind(transitionEvent, function (evt) {
                console.log('got a css transition event', evt);

                var phase = scope.$root.$$phase;

                if (phase === '$apply' || phase === '$digest') {
                    fn();
                } else {
                    scope.$apply(fn);
                }
            });
        },
    };
 }]);
  

затем измените свой html следующим образом:

 <div id="mycontainer" ng-controller="mycontroller" my-transition-end="callSomeScopeFunctionYouDefined()">