【问题标题】:AngularJS - Find end of collapse animationAngularJS - 找到折叠动画的结束
【发布时间】: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 说明了问题。

【问题讨论】:

    标签: javascript html angularjs angular-ui-bootstrap


    【解决方案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 可能对每种情况都不够健壮,但对于您正在做的事情应该足够了。
    猜你喜欢
    • 1970-01-01
    • 2015-01-05
    • 2018-05-22
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    相关资源
    最近更新 更多