Javascript Don';在ng hide CSS转换完成之前是否显示元素?

Javascript Don';在ng hide CSS转换完成之前是否显示元素?,javascript,angularjs,animation,Javascript,Angularjs,Animation,这个问题很简单,但我在实现上遇到了麻烦。如果我有以下DOM设置: <h1 class="fade" ng-repeat="child in parent.children" ng-show="parent.activeChild== child ">@{{ child.title }}</h1> 但是,这最终会产生: 本质上,我想链接我的动画。我已经试着阅读了,但是我在语法上遇到了问题,无法达到我想要的效果 我见过有棱角的文档有这样的东西: app.animation

这个问题很简单,但我在实现上遇到了麻烦。如果我有以下DOM设置:

<h1 class="fade" ng-repeat="child in parent.children" ng-show="parent.activeChild== child ">@{{ child.title }}</h1>
但是,这最终会产生:

本质上,我想链接我的动画。我已经试着阅读了,但是我在语法上遇到了问题,无法达到我想要的效果

我见过有棱角的文档有这样的东西:

app.animation('.fade', [function() {
    return {
        addClass: function(element, className, doneFn) {
        },
        removeClass: function(element, className, doneFn) {
        }
    };
}]);
  • 什么是
    className
    ?淡入淡出时,我想申请的是哪门课?我期待的课程
  • 什么是
    doneFn
    ?我假设它是一个在动画完成后运行的函数?里面有什么
  • 如果我已经有了一个
    doneFn
    ,那么在
    addClass
    removeClass
    函数中该怎么做
目标
我想直接使用Angular的ngAnimate模块生成一个工作动画,使用CSS或JS。我怎样才能做到这一点呢?

为什么对每个标题使用单独的
。您可以使用单个
标记来显示标题

我已经为你的问题创建了一个演示,我已经成功地完成了你的要求

已更新

注意,代码被编辑为使用
ngAnimate
模块。当您使用
ngAnimate
模块时,当您隐藏一个元素时,它将创建一个类
.ng hide

这是你的应用程序的控制器

app2.controller("testController", ["$scope", "$timeout", function ($scope, $timeout) {

    $scope.heading = {};
    $scope.heading.show = true;

    $scope.parent = {};
    $scope.parent.children = ["A", "B", "C", "D"];
    $scope.parent.activeChild = "A";

    $scope.changeHeading = function (child) {
        $timeout(function () {
            $scope.parent.activeChild = child;
            $scope.heading.show = true;
        }, 1000);

    }
}]);
你的html页面应该是这样的

<div ng-controller="testController">
    <h1 class="myAnimateClass" ng-show="heading.show" ng-class="{fadeIn : heading.fadeInModel==true, fadeOut : heading.fadeOutModel}"> {{parent.activeChild}} </h1>
    <p ng-repeat="child in parent.children" ng-click="heading.show = false;changeHeading(child)">{{child}}</p>
</div>
解释

为了满足您的需求,我在angularJS中使用了
ng类
$timeout

您可以看到,我只有一个
标签来显示您的标题。当我更改标题时,我只是更改它的绑定属性
$scope.parent.activeChild

我使用了两个作用域变量
$scope.heading.fadeOutModel
$scope.heading.fadeInModel
动态添加和删除类
fadeIn
fadeOut

当用户单击更改标题时,我已将类<代码>淡出添加到您的标题中。因此,这将显示淡出的动画。我还在app.js中启动了一个函数,
changeHeading()

您可以看到,我强制角度传感器等待
1000
毫秒以完成淡出动画。在此之后,它将把所选标题替换为新标题,并添加一个类
fadeIn
。因此,它将启动淡入动画


希望这对你有帮助

根据选择显示特定元素的更具动画效果的方法是使用
ngSwitch
。此指令用于基于范围表达式有条件地交换模板上的DOM结构。这是一本书

HTML

<button ng-repeat="item in items" ng-click="parent.selection = item">{{ item }}</button>
<div class="animate-switch-container" ng-switch on="parent.selection">
  <div class="animate-switch" ng-switch-when="foo">foo</div>
  <div class="animate-switch" ng-switch-when="bar">bar</div>
</div>
  <body ng-controller="MainCtrl">
    <h1><span class="fade" ng-repeat="child in parent.children" ng-show="parent.activeChild == child ">@{{child.title}}</span></h1>
    <button ng-repeat="child in parent.children" ng-click="parent.activeChild = child">{{ child.title }}</button>
  </body>
CSS

.animate-switch-container {
  position:relative;
  height:40px;
  overflow:hidden;
}
.animate-switch {
  padding:10px;

}
.animate-switch.ng-animate {
  transition:opacity 1s ease;

}
.animate-switch.ng-leave.ng-leave-active,
.animate-switch.ng-enter {
  opacity: 0;
}
.animate-switch.ng-leave,
.animate-switch.ng-enter.ng-enter-active {
  opacity: 1;
}
.fade {
  opacity: 1;
  position: relative;
}

.fade.ng-hide-add {
    transition:opacity 1s ease;
    position: absolute;
}

.fade.ng-hide-remove {
    transition:opacity 1s ease 1s;
    position: absolute;
}

.fade.ng-hide-add {
  opacity:1;
}

.fade.ng-hide-add.ng-hide-add-active {
  opacity:0;
}

.fade.ng-hide-remove {
    opacity:0;
}

.fade.ng-hide-remove.ng-hide-remove-active {
    opacity:1;
}

这不是链接,而是直接使用Angular的ngAnimate模块的工作动画。这里还有一个。

您可以使用
.animation
定义基于Javascript的动画。例如,您定义为
addClass
removeClass

app.animation('.fade', [function() {
    return {
        addClass: function(element, className, doneFn) {
        },
        removeClass: function(element, className, doneFn) {
        }
    };
}]);
当Angular检测到您正在从以下方法之一的元素中添加或删除类时,将调用:

  • {{}
    在模板中插入。例如,
  • 在模板中使用
    ng类
    。例如,
  • 在指令中使用
    $animate
    服务。例如,
    $animate.addClass(元素“淡入”)或
    $animate.removeClass(元素“淡入”)
什么是类名?淡入淡出时,我想申请的是哪门课?我期待的课程

在本例中,它将是
fade
。不可否认,这有点奇怪,因为在示例中已经很清楚这是所涉及的类名。但是,如果在同一个摘要循环中,您将多个类添加到同一个元素中,那么它们的串联将作为此字符串传递

doneFn的本意是什么?我假设它是一个在动画完成后运行的函数?里面有什么

这是一个函数,您可以在定义的Javascript动画完成后调用它。例如,要定义不作为全部的动画,请执行以下操作:

addClass: function(element, className, doneFn) {
  doneFn();
},
调用它会告诉Angular动画已完成。这将从元素中删除
ng animate

如果我已经有了一个doneFn,那么在addClass和removeClass函数中该怎么做

您可以在其中添加一些代码,可能使用超时或第三方库,以某种方式更改元素。完成后,调用
doneFn
。例如,一步不透明度“动画”:

我想直接使用Angular的ngAnimate模块生成一个工作动画,使用CSS或JS

这与上面的答案没有多大关系!如果我在做一个真实的案例,我强烈怀疑我会绝对地定位元素,因为至少我能想到的其他任何东西都有点过于复杂

但是,如果确实希望使用ngAnimate链接动画,一种可能的方法是使用
$animate.addClass
$animate.removeClass
在完成时返回承诺。为了链接到隐藏元素时返回的承诺的末尾,必须从某种中心位置调用它,并跟踪哪个元素是可见的、隐藏的和显示的

一种方法是使用2个自定义指令。每个元素上都会有一个元素用于显示和隐藏,这非常类似于
ngShow
。另一个是父指令,它在任何时候都只允许一个元素可见,并且在添加
ng hide
后链删除
ng hide
类(和相关动画)。指令必须传达,co
addClass: function(element, className, doneFn) {
  doneFn();
},
addClass: function(element, className, doneFn) {
  element.css('opacity', 0.5);
  setTimeout(function() {
    doneFn();
  }, 1000);
},
<div ng-show-unique-controller>
  <h1 class="fade" ng-repeat="child in parent.children" ng-show-unique="parent.activeChild == child">@{{child.title}}</h1>
</div>
app.directive('ngShowUniqueController', function($q, $animate) {
  return {
    controller: function($scope, $element) {
      var elements = [];
      var expressions = [];
      var watchers = [];
      var unregisterWatchers = null;
      var visibleElement = null;

      function registerWatchers() {
        unregisterWatchers = $scope.$watchGroup(expressions, function(vals) {
          var newCurrentIndex = vals.indexOf(true);
          var addPromise;

          if (visibleElement) {
            // Set a fixed height, as there is a brief interval between
            // removal of this class and addition of another
            $element.css('height', $element[0].getBoundingClientRect().height + 'px'); 
            addPromise = $animate.addClass(visibleElement, 'ng-hide');
          } else {
            addPromise = $q.when();
          }
          visibleElement = elements[newCurrentIndex] || null;
          if (!visibleElement) return;

          addPromise.then(function() {
            if (visibleElement) {
              $animate.removeClass(visibleElement, 'ng-hide').then(function() {
                $element.css('height', '');
              });
            }
          })
        });
      }   

      this.register = function(element, expression) {
        if (unregisterWatchers) unregisterWatchers();
        elements.push(element[0]);
        expressions.push(expression);
        registerWatchers();

        // Hide elements initially
        $animate.addClass(element, 'ng-hide');
      };

      this.unregister = function(element) {
        if (unregisterWatchers) unregisterWatchers();
        var index = elements.indexOf(element[0]);
        if (index > -1) {
          elements.splice(index, 1);
          expressions.splice(index, 1);
        }
        registerWatchers();
      };
    } 
  };
});

app.directive('ngShowUnique', function($animate) {
  return {
    require: '^ngShowUniqueController',
    link: function(scope, element, attrs, ngShowUniqueController) {
      ngShowUniqueController.register(element, function() {
        return scope.$eval(attrs.ngShowUnique);
      });

      scope.$on('$destroy', function() {
        ngShowUniqueController.unregister(element);
      });
    }
  };
});
.fade {
  opacity: 1;
  position: relative;
}

.fade.ng-hide-add {
    transition:opacity 1s ease;
    position: absolute;
}

.fade.ng-hide-remove {
    transition:opacity 1s ease 1s;
    position: absolute;
}

.fade.ng-hide-add {
  opacity:1;
}

.fade.ng-hide-add.ng-hide-add-active {
  opacity:0;
}

.fade.ng-hide-remove {
    opacity:0;
}

.fade.ng-hide-remove.ng-hide-remove-active {
    opacity:1;
}
  <body ng-controller="MainCtrl">
    <h1><span class="fade" ng-repeat="child in parent.children" ng-show="parent.activeChild == child ">@{{child.title}}</span></h1>
    <button ng-repeat="child in parent.children" ng-click="parent.activeChild = child">{{ child.title }}</button>
  </body>
element.addEventListener('transitionend', callback, false);