Angular.js animation

I have a block with ng-repeat , which is defined as follows:

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

Currently, I can switch between these blocks by clicking on certain elements. It works through ng-show="isPageSelected(item.page)" , as you might have guessed. Everything works fine, but they switch instantly, and I want to add animation, a simple fade / fade will do.

So, a block that is no longer selected should disappear, and when it is gone, the new block must disappear. When I use ngAnimate , they disappear and disappear at the same time. I need the first block to completely disappear and be hidden with display: none; , and when it is done, the next block should appear and disappear. This is a pretty simple task when using jQuery, but how do I do it elegantly using Angular.js

I have a strong suspicion that Angular.js is not a good choice for a site with complex animations.

EDIT: To simplify my question, all I have to do is

  • By clicking the mouse button, start the animation;
  • When the animation is complete, change the model;
  • Run another animation.

Since I need to change the model after the animation, it may not be possible to do this with pure CSS. The only way to know the animation of individual elements in angular is to create a directive, pass the scope variable to the directive, create an observer for this variable in the directive, and then change the variable from the controller:

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

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

I suppose this will work, but it seems really bloated to create a directive just for that. Also, how do I change $scope.page to this approach only after the animation finishes? Add another scope variable just to start the animation and somehow change $scope.page when the animation is finished? This can be done using the ngFx module, but the amount of code that is required is just ridiculous. At the moment, I think adding jQuery animation to the controller would be a more beautiful way to solve it.

EDIT: what it looks like with jQuery animation:

 $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 as much as the directive mode, but I have to use a CSS selector and it just feels โ€œnon-angularโ€. Do you guys use something similar when working with animations?

EDIT: A somewhat similar approach using 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 don't use CSS selectors, but it still looks awful. I have to define the scope variable for the animation, and then check if the animation is running. I feel like I'm missing something really obvious.

+5
source share
4 answers

Perhaps this will help you, and in your case, you do not need to wait for the animation to finish. If your pages have the position css: absolute and are in the container with the position: relative, then they share the same place and do not appear one below the other during the animation. With this setting, you can rephrase or delay the animation of the show.

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/

Edit: If u uses a filter in ng-repeat instead of ng-show to show a selected page like this

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

then the pages are added and removed from dom and angular add the classes ng-enter, ng-enter-active and ng-leave ng-leave-active

but the animation can be defined similarly, see the script: http://jsfiddle.net/o944epzy/

+7
source

Effectively, you need to use CSS to show and hide elements from your ng-repeat; when you use ngAnimate, do not forget to enter it into your module.

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

Doing this when you add / remove an item from the ng-repeat source. Angular will add and remove the ng-enter, ng-leave class. Here is a good tutorial on animation with ngAnimate.

In your own case, you want to change the page. I suggest you too many elements to display all at once.

You can declare two variables in your scope:

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

and after that in your template you can do the following:

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

This template will show only the necessary elements depending on the page number and the number of elements on the page. A 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 need to use a button that allows you to view 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 fading to the animation for the new elements, so declare in your css these classes following the class of your items (here 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 when the item is deleted by replacing enter with leave .

I hope he answers your question.

+2
source

Effectively, you need to use CSS to show and hide elements from your ng-repeat; when you use ngAnimate, do not forget to enter it into your module.

0
source

You can add the desired transition to the CSS class of the element to display / hide:

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

More details here: https://docs.angularjs.org/api/ng/directive/ngShow#example

In fact, using CSS is the โ€œrightโ€ way to do this, even though it may seem un-angular.

-1
source

Source: https://habr.com/ru/post/1210651/


All Articles