AngularJS - 找到折叠动画的结束

Posted

技术标签:

【中文标题】AngularJS - 找到折叠动画的结束【英文标题】:AngularJS - Find end of collapse animation 【发布时间】:2014-11-29 13:51:22 【问题描述】:

我对@9​​87654321@ 的collapse 指令有一个简单的问题。我有一个<select> 菜单。当有人更改菜单时,内容也会发生变化。但是,我想在应用这些更改之前添加一个动画。具体来说,我希望该部分在显示新内容之前折叠和取消折叠。我可以折叠它,但我想知道如何检测折叠何时完成,以便我可以展开它。

我可以使用我目前使用的$timeout方法,但是感觉“hackish”和“不正确”,因为如果折叠动画的时间发生变化,那么我必须再次更改时间。

相关代码:

.directive("myBufferAnimation", function($timeout) 
    var ignoreFirst = true;
    return function(scope, element, attrs) 
        scope.$watch("selectBuffer", function(newValue) 
            if (ignoreFirst) 
                ignoreFirst = false;
                return;
            


            scope.toCollapse = true;    
            // Detect end of animation here?
            // Bogus solution, as this just waits for one second rather than listening for the end of animation
            $timeout(function() 
               scope.selected = newValue;
               scope.toCollapse = false;
            , 1000);
        );
    
);

这个jsfiddle 说明了问题。

【问题讨论】:

【参考方案1】:

查看 angularui bootstrap 的 collapse 指令,它使用 $transition 服务执行动画,但它不会暴露以挂钩到服务返回的承诺。但是,它确实会更改具有collapse 指令的元素的类名。您可以通过在元素的 class 属性上放置一个监视来使用它来确定折叠动画何时完成。

下面是在元素上监视类的代码的工作示例。我进行了更改以使用ng-change 来执行动画,而不是观看selectBuffer。这消除了对 ignoreFirst 变量的需要。

angular.module("testApp", ["ui.bootstrap"]).controller("TestCtrl", function($scope) 
  // This would actually be fetched from an ajax call
  $scope.data = [
    "title": "Title 1",
    "content": "Content 1"
  , 
    "title": "The Second Title",
    "content": "Some content goes here"
  , 
    "title": "Title 3",
    "content": "Content 3"
  ];
  $scope.selected = $scope.data[0];
  $scope.selectBuffer = $scope.data[0];
  $scope.toCollapse = false;
).directive("myBufferAnimation", function($timeout) 
  return function(scope, element, attrs) 
    scope.valueChanged = function() 
      scope.toCollapse = true;
      // save off the unregister method returned from $watch call.
      var unregisterWatch = scope.$watch(function() 
        return element.attr('class');
      , function(newClass, oldClass) 
        // If the newClass is 'collapse' and the oldClass is 'collapsing'
        // this means that the collapsing animation has completed.
        if (newClass.indexOf("collapse") !== -1 && oldClass.indexOf("collapsing") !== -1) 
          scope.selected = scope.selectBuffer;
          scope.toCollapse = false;
          // unregister the $watch on the class attribute
          // since it is no longer needed.
          unregisterWatch();
        
      );
    ;
  
);
<!DOCTYPE html>
<html>

<head>
  <link data-require="bootstrap-css@3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
  <script src="https://code.angularjs.org/1.2.26/angular.js"></script>
  <script data-require="jquery@*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
  <script data-require="bootstrap@3.1.1" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
  <script data-require="angular-ui-bootstrap@0.11.0" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
</head>

<body>
  <div ng-app="testApp">
    <div ng-controller="TestCtrl">
      <select ng-options="opt as opt.title for opt in data" ng-model="selectBuffer" ng-change="valueChanged()"></select>
      <br />
      <div my-buffer-animation="" collapse="toCollapse" class="test">
        <h1>selected.title</h1>

        <p>selected.content</p>
      </div>
    </div>
  </div>
</body>

</html>

【讨论】:

我注意到你使用了newClass === "collapse"。即使有其他类,这也能工作(因为newClass 可能是"collapse my-custom-class" 或其他东西,对吧?) 更新最后一条评论:我将 test-class 添加到 divmy-buffer-animation 指令和上面的代码停止工作,但我认为这可以使用 element.hasClass 或等效解决。 我尝试测试您建议的更改,但我在使用的浏览器中遇到错误,这可能是由于使用了 classList 以及 angularjs 获取旧值以传递给 watch 函数的方式.我改为使用indexOf 来确定是否存在应该处理具有多个类名的类名。 indexOf 可能对每种情况都不够健壮,但对于您正在做的事情应该足够了。

以上是关于AngularJS - 找到折叠动画的结束的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能使这个动画更流畅?

执行前不显示AngularJS代码[重复]

使用 angularjs 列出重新排序动画

AngularJS - 动画回调/序列

高度约束动画“跳跃”

Node.js/AngularJS 前端调用 Spring Boot API 后端