Angular.js动画

时间:2015-01-08 10:12:26

标签: javascript css angularjs animation angularjs-directive

我有一个ng-repeat的块,其定义如下:

<div ng-show="isPageSelected(item.page)" class="block" ng-repeat="item in data">
  ...
</div>

目前我可以通过点击某些元素在这些块之间切换。它可以通过您可能已经猜到的ng-show="isPageSelected(item.page)"工作。这一切都很好,但他们正在立即切换,我想添加一个动画,一个简单的淡入/淡出将做。

因此,不再选择的块应该淡出,当它消失时,新的块应该淡入。当我使用ngAnimate时,它们会淡入并同时淡出。我需要第一个块完全消失并隐藏display: none;,当它完成后,下一个块应该出现并淡入。这是一个相当简单的任务,当使用jQuery时,但我该怎么办用Angular.js优雅地做到这一点?

我非常怀疑Angular.js对于具有复杂动画的网站来说不是一个好的选择。

编辑:为了简化我的问题,我需要做的就是

  1. 点击按钮,启动动画;
  2. 动画完成后,更改模型;
  3. 运行另一个动画。
  4. 由于我需要在动画后更改模型,因此可能无法通过纯CSS来实现。我知道在angular中触发特定元素动画的唯一方法是创建一个指令,将一个范围变量传递给指令,在指令中为该变量创建观察者,然后从控制器中更改变量:

    <div animation="page"></div>
    

    app.directive('animation', function(){
        return {
            scope: { page: '=animation' },
            link: function(scope, element){
                scope.$watch('page', function(newVal){
                    ...
                });
            }
        };
    });
    

    我想它会起作用,但为此创建一个指令似乎真的很臃肿。另外,只有在动画完成后,我才会用这种方法更改$scope.page?添加另一个范围变量只是为了触发动画,并在动画完成后以某种方式更改$scope.page?使用ngFx模块可以做到这一点,但它所需的代码量非常荒谬。在这一点上,我认为将jQuery动画添加到控制器将是解决它的更漂亮的方法。

    编辑:这是jQuery动画的样子:

    $scope.changePage = function(page) {
      $('.block').animate({opacity: 0}, 500, function(){
        $scope.page.id = page;
        $scope.$apply();
        $(this).animate({opacity: 1}, 500);
      });
    };
    

    它工作得很好,并不像指令的方式那么冗长,但我必须使用CSS选择器,而且感觉非常“非常”&#34;。你们在处理动画时会使用类似的东西吗?

    编辑:使用ngFx的某种类似方法:

        <div ng-hide="switchPageAnimation" 
                 class="block fx-fade-normal fx-speed-300 fx-trigger">
    

    在控制器中:

      $scope.switchPageAnimation = false;
    
      $scope.changePage = function(page) {
        if($scope.page.id === page || $scope.switchPageAnimation) return;
        $scope.switchPageAnimation = true;
        $scope.$on('fade-normal:enter', function(){
          $scope.page.id = page;
          $scope.switchPageAnimation = false;
        });
      };
    

    我没有使用CSS选择器,但它看起来很糟糕。我必须为动画定义范围变量,然后检查动画是否已经在运行。我觉得我错过了一些非常明显的东西。

4 个答案:

答案 0 :(得分:7)

也许这会对你有所帮助,在你的情况下等待动画完成是没有必要的。如果您的页面具有css位置:绝对并且位于具有position:relative的容器中,那么它们共享相同的位置,并且在动画时不会一个在另一个下面显示。使用此设置,您可以交叉淡化或延迟节目动画

转换延迟:

.container1{
    position: relative;
    height:400px;
}

.block1{
    position:absolute;
}
.block1.ng-hide-add-active {
    display: block!important;
    -webkit-transition: 2s linear all;
    transition: 2s linear all;
}
.block1.ng-hide-remove-active {
    display: block!important;
    -webkit-transition: 2s linear all;
    transition: 2s linear all;
    -webkit-transition-delay: 2s;
    transition-delay: 2s;
}
.block1.ng-hide {
    opacity: 0;
}

http://jsfiddle.net/ncrs4gz0/

修改 如果你在ng-repeat中使用过滤器而不是ng-show来显示像这样的选定页面

<div  class="block1" ng-repeat="item in data | filter:isPageSelected">

然后从dom和angular添加类中添加和删除页面ng-enter,ng-enter-active和ng-leave ng-leave-active

但动画可以定义类似于小提琴:http://jsfiddle.net/o944epzy/

答案 1 :(得分:2)

实际上,您必须使用CSS来显示和隐藏ng-repeat中的元素; 当你使用ngAnimate时,不要忘记将它注入你的模块。

.module('myModule', [  'ngAnimate', ...

在您添加/删除重复数据源中的元素时执行此操作。 Angular将添加和删除类ng-enter, ng-leaveHere是一个关于使用ngAnimate的动画的好教程。

在您自己的情况下,您想要更改页面。我建议您有太多项目可以同时显示所有内容。

您可以在范围内声明两个变量:

$scope.elemByPage = 5;
$scope.page = 0;
$scope.nbPages = ...; // I let you do the maths ;)

在你的模板中你可以做到这一点:

<div class="my-repeat-item" data-ng-repeat="item in data | pager:page:elemByPage">
 {{item.xxx}}           
</div>

此模板仅显示页码功能和每页元素数量所需的项目。 寻呼机是一个简单的过滤器,它可以解决问题

.filter('pager',[function(){
        return function(items, page, nbElemByPage) {

            if(!nbElemByPage || nbElemByPage < 1) {
                return items;
            }

            var nbPages = Math.floor(items.length/nbElemByPage);
            if(nbPages<1) {
                return items;
            }

            var startIndex = page*nbElemByPage;

            return items.splice(startIndex, nbElemByPage);
        };
    }])

现在您只需使用可以浏览项目的按钮

<button data-ng-click="page = page - 1"/>Prev page</button>
<button data-ng-click="page = page - 1"/>Next page</button>

要完成您想要在新项目上添加淡入淡出动画,请在您的css中声明这些类跟随您的项目类别(此处为my-repeat-item

.my-repeat-item.ng-enter {
    transition: 0.6s ease all;
    opacity:0;
}
.my-repeat-item.ng-enter.ng-enter-active {
    opacity:1;
}

通过将enter替换为leave,您可以在删除项目时执行相同的操作。

希望它能回答你的问题。

答案 2 :(得分:0)

实际上,您必须使用CSS来显示和隐藏ng-repeat中的元素;当你使用ngAnimate时,不要忘记将它注入你的模块。

答案 3 :(得分:-1)

您可以将所需的过渡添加到要显示/隐藏的元素的CSS类中:

animate-show.ng-hide-add.ng-hide-add-active,
.animate-show.ng-hide-remove.ng-hide-remove-active {
  -webkit-transition: all linear 0.5s;
  transition: all linear 0.5s;
}

在此处查看更多信息: https://docs.angularjs.org/api/ng/directive/ngShow#example

事实上,使用CSS是“正确的”&#39;即使它可能感觉没有角度,也可以这样做。