简体   繁体   English

Angular.js动画

[英]Angular.js animations

I have a block with ng-repeat that is defined like this: 我有一个ng-repeat的块,定义如下:

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

Currently I can switch between those blocks, by clicking certain elements. 目前,我可以通过单击某些元素在这些块之间切换。 It works via ng-show="isPageSelected(item.page)" as you might have guessed. 它可以通过ng-show="isPageSelected(item.page)" ,你可能已经猜到了。 It all works fine, but they are switching instantly and I want to add an animation, a simple fade in/fade out will do. 这一切都很好,但他们正在立即切换,我想添加一个动画,一个简单的淡入/淡出将做。

So, the block that is no longer selected should fade out and when it's gone a new block should fade in. When I'm using ngAnimate they fade in and fade out simultaneously. 因此,不再选择的块应该淡出,当它消失时,新的块应该淡入。当我使用ngAnimate它们会淡入并同时淡出。 I need the first block to disappear completely and be hidden with display: none; 我需要第一个块完全消失并隐藏display: none; and when it's done the next block should appear and fade in. It's a rather straightforward task when using jQuery, but how do I do that elegantly with Angular.js? 当它完成时,下一个块应该出现并淡入。使用jQuery时这是一个相当简单的任务,但是我如何使用Angular.js优雅地完成它?

I have a strong suspicion that Angular.js isn't exactly a good choice for a site with complex animations. 我强烈怀疑Angular.js对于具有复杂动画的网站来说不是一个好的选择。

EDIT: To simplify my question, all I need to do is 编辑:为了简化我的问题,我需要做的就是

  1. On a button click start an animation; 在按钮上单击开始动画;
  2. When an animation has been finished, change model; 动画完成后,更改模型;
  3. Run another animation. 运行另一个动画。

Since I need to change the model after an animation, it's probably not possible to do it via pure CSS. 由于我需要在动画后更改模型,因此可能无法通过纯CSS来实现。 The only way I know of triggering animations on specific elements in angular is to create a directive, pass a scope variable into the directive, create watcher for that variable in the directive and then change the variable from the controller: 我知道在angular中触发特定元素动画的唯一方法是创建一个指令,将一个范围变量传递给指令,在指令中为该变量创建观察者,然后从控制器更改变量:

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

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

I guess it would work, but it seems really bloated to create a directive just for that. 我想它会起作用,但为此创建一个指令似乎真的很臃肿。 Also, how would I change $scope.page with this approach only when the animation has been finished? 另外,只有在动画完成后,我$scope.page用这种方法更改$scope.page Add another scope variable just to trigger an animation and somehow change $scope.page when an animation has been finished? 添加另一个范围变量只是为了触发动画,并在动画完成后以某种方式更改$scope.page It's possible to do it with ngFx module, but the amount of code it takes is just ridiculous. 使用ngFx模块可以做到这ngFx ,但它所需的代码量非常荒谬。 At this point I think adding jQuery animations to the controller would be a prettier way to solve it. 在这一点上,我认为将jQuery动画添加到控制器将是一个更好的解决方法。

EDIT: That's how it looks like with jQuery animations: 编辑:这就是jQuery动画的样子:

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

It works fine and it's not quite as verbose as the way with directives, but I have to use CSS selectors and that's just feels very "unangular". 它工作得很好,并不像指令的方式那么冗长,但我必须使用CSS选择器,这只是感觉非常“不整齐”。 Do you guys use something similar when dealing with animations? 你们在处理动画时会使用类似的东西吗?

EDIT: Somewhat similar approach using ngFx : 编辑:使用ngFx有点类似的方法:

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

In the controller: 在控制器中:

  $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;
    });
  };

I'm not using CSS selectors, but still it looks awful. 我没有使用CSS选择器,但它看起来很糟糕。 I have to define a scope variable for the animation and then check if the animation is already running. 我必须为动画定义范围变量,然后检查动画是否已经在运行。 I feel like I am missing something really obvious. 我觉得我错过了一些非常明显的东西。

Maybe this will help you and it is not necessary in your case to wait for the animation to finish. 也许这会对你有所帮助,在你的情况下等待动画完成是没有必要的。 If your pages have css position: absolute and are in a container with position: relative then they share the same place and are not shown one below the other while animation. 如果您的页面具有css位置:绝对并且位于具有position:relative的容器中,那么它们共享相同的位置,并且在动画时不会一个在另一个下面显示。 With this setting you can crossfade or delay the show animation 使用此设置,您可以交叉淡化或延迟显示动画

transition-delay: 过渡延迟:

.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/ http://jsfiddle.net/ncrs4gz0/

Edit: If u use a filter in ng-repeat instead of ng-show to show a selected page like this 编辑:如果你使用ng-repeat而不是ng-show中的过滤器来显示这样的选定页面

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

then the pages are added and removed from the dom and angular add classes ng-enter , ng-enter-active and ng-leave ng-leave-active 然后从dom和angular add类添加和删除页面ng-enter,ng-enter-active和ng-leave ng-leave-active

but the animation can be defined similar see fiddle : http://jsfiddle.net/o944epzy/ 但动画可以定义类似看小提琴: http//jsfiddle.net/o944epzy/

Effectively you have to use CSS for showing and hiding elements from your ng-repeat; 实际上,您必须使用CSS来显示和隐藏ng-repeat中的元素; when you use ngAnimate, do not forget to inject it in your module. 当你使用ngAnimate时,不要忘记将它注入你的模块中。

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

Doing that when you will add/remove an element from you ng-repeat source of data. 当您添加/删除重复数据源中的元素时,请执行此操作。 Angular will add and remove the class ng-enter, ng-leave . Angular将添加和删除类ng-enter, ng-leave Here is a good tutorial about animation with ngAnimate. 是一个关于ngAnimate动画的好教程。

In your own case you want to change page. 在您自己的情况下,您想要更改页面。 I suggest you have too many items for displaying all at once. 我建议您有太多项目可以同时显示所有内容。

You can declare in your scope two variable : 您可以在范围中声明两个变量:

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

and after in your template you can do simply this: 在您的模板中,您可以这样做:

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

This template will only show the needed items in function of the page number and number of elements per page. 此模板仅显示页面编号和每页元素数量所需的项目。 Pager is a simple filter and it does the trick 寻呼机是一个简单的过滤器,它可以解决问题

.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);
        };
    }])

Now you just have to use button that will allow you to browser your items 现在您只需使用按钮即可浏览您的项目

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

To finish you want to add a fade in animation on new items so declare in your css these classes following the class of your items (here my-repeat-item ) 要完成你想在新项目上添加淡入淡出的动画,所以在你的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;
}

You can do the same thing when a item is removed by replacing enter with leave . 你可以做,当项目被替换去除同样的事情, enterleave

Hope it will answer to your question. 希望它能回答你的问题。

Effectively you have to use CSS for showing and hiding elements from your ng-repeat; 实际上,您必须使用CSS来显示和隐藏ng-repeat中的元素; when you use ngAnimate, do not forget to inject it in your module. 当你使用ngAnimate时,不要忘记将它注入你的模块中。

You can add your desired transition to the CSS class of the element to show/hide: 您可以将所需的过渡添加到要显示/隐藏的元素的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;
}

See more here: https://docs.angularjs.org/api/ng/directive/ngShow#example 点击此处查看: https//docs.angularjs.org/api/ng/directive/ngShow#example

In fact, using CSS is the 'right' way to do it even though it even though it might feel un-angular. 事实上,使用CSS是“正确”的方式,即使它可能感觉没有角度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM