How can i wait for animation to end in angular.js - angularjs

I'm using animate.css to do some animations on my site, but i want a certain animation to occur right after the other one ended, for example i have this css:
.pageRenderer.ng-enter{
animation: fadeIn 1s;
}
.pageRenderer.ng-leave{
animation: bounceOutLeft 1s;
}
And this simple html:
<div ng-repeat='page in pages' style='position:relative'>
<div ng-if="$index == pageToShow" class='pageRenderer'>
<h2>{{page.title}}</h2>
<div ng-repeat='quest in page.quests'>
<div ng-switch on="quest.ui.type">
<div ng-switch-when="ms-select-single" >
<div ms-select-single quest='quest'></div>
</div>
...
</div>
</div>
</div>
When i turn to next page (I have a button that does it), i want first to my ng-leave to do it's job and leave, and only than do the enter, not simultaneously...
Is it possible without any use of angular at all? if not, What are to be my options?

You can try different solutions:
add a delay to the ng-leave class
animation-delay: 1s;
put your animations when ng-enter is active and ng-leave is active (not sure about this solution, I usually use transitions and not animations, but give it a try)
.pageRenderer.ng-enter.ng-enter-active {
animation: fadeIn 1s;
}
.pageRenderer.ng-leave.ng-leave-active {
animation: bounceOutLeft 1s;
}

Related

Moving an element from right to left using CSS3 transitions on load of the document

I want to add a transition property to an element which contains text coming from an angular controller.
I want to move it from right to left when the document loads. Is there any way to do that. here is my sample code.
Index file excerpt
<div class="logArena">
<ul class="timeline">
<li ng-repeat="log in changelogCtrl.logs | orderBy: '-dateObj'">
<span class="direction-l">
<span class="time-wrapper">
<span class="time">
{{log.date}}
</span>
</span>
</span>
<div class="direction-r">
<div class="flag-wrapper">
<div class="flag">
<span id="axis">
<span class="move-left">
<strong>{{log.module}}</strong> <strong class="fa fa-long-arrow-right"></strong> {{log.subModule}}
</span>
</span>
</div>
</div>
<div class="desc">
{{log.desc}}
</div>
</div>
</li>
</ul>
</div>
CSS Except (Right now I tried it with hover but it didn't work too, but I want it to automatically come from right to left on page load.)
#axis:hover .move-left{
transform: translate(350px,0);
-webkit-transform: translate(350px,0); /** Safari & Chrome **/
-o-transform: translate(350px,0); /** Opera **/
-moz-transform: translate(350px,0); /** Firefox **/
}
Use a CSS animation and define the values of the translation inside the keyframes. The forwards value will keep your element with the style of the last keyframe encountered.
CSS
.move-left {
animation: moveleft 2s 1 normal forwards;
}
#keyframes moveleft {
from { transform: translateX(0); }
to { transform: translateX(350px); }
}
codepen demo
This will wait just until the presence of that element on the DOM but, if you need to wait the full document load (including images and heavy assets) just add a class (e.g. .load) to the .move-left element on load event of the window and fire the animation only if the class has been applied, so the JS and CSS selector would be
Javascript
window.addEventListener("load", function(event) {
document.querySelector('.move-left').classList.add('load');
});
CSS
.move-left.load {
animation: moveleft 2s 1 normal forwards;
}
You could just use Jquery and .addClass and .removeClass.
For example
jQuery(document).ready(function($){
$('#axis').click(function(){
$('//What you want the class to be added too / Moved').addClass('move-left');
)};
)};
You can use animation property of CSS-3 in combination with translateX() property.
.row {
animation: 1s ease-out 0s 1 slide;
}
#keyframes slide {
0%{ transform: translateX(100%);}
100%{ transform: translateX(0%);}
}
Check out this answer.

Angular/CSS - Animate shifting of content when new elements are dynamically added

Angular animation noob here.
I can successfully animate content onto the page using ngAnimate. However, when my new content slides in, all of the content below it jumps down to its new position. Likewise, when the new content is removed the following content jumps back up. Is there an angular way to animate the new position of the following content?
<button class="button" ng-if="typingResponse">
Submit!
</button>
<div class="response-section">
<label class="item item-input item-stacked-label">
<span class="input-label">Response</span>
<textarea></textarea>
</label>
</div>
.button.ng-enter {
-webkit-animate: slideInLeft 1s;
animation: slideInLeft 1s;
}
.button.ng-leave {
-webkit-animate: slideOutLeft 1s;
animation: slideOutLeft 1s;
}
#klauskpm got me most of the way there, and this blog post was the missing piece.
Solution:
Put the button inside of a div
Set the initial max-height of the div to 0px
Specify a transition on the div's max-height property
When the button is to be displayed, increase the max-height property of the div
Updated code:
<div class="button-container" ng-class="{'has-button': typingResponse}">
<button class="button" ng-if="typingResponse">
Submit
</button>
</div>
<div class="response-section">
<label class="item item-input item-stacked-label">
<span class="input-label">Response</span>
<textarea></textarea>
</label>
</div>
.button.ng-enter {
-webkit-animate: slideInLeft $slide-dur;
animation: slideInLeft $slide-dur;
}
.button.ng-leave {
-webkit-animate: slideOutLeft $slide-dur;
animation: slideOutLeft $slide-dur;
}
.button-container {
max-height: 0px;
transition: max-height $slide-dur linear;
-webkit-transition: max-height $slide-dur linear;
}
.button-container.has-button {
max-height: 100px;
}

ngAnimate on route change using different animation according to class element

I want to simulate the horizontal parallax effect on page transition, using the classes ng-enter and ng-leave added by ngAnimate.
The idea is to use different speed for the elements in the page, to have a "3d deep effect" when the elements slide to the left. This is my not-working code
<style>
#keyframes slideOutLeft {
to { transform: translateX(-100%); }
}
#container.ng-enter .layer-one
{animation: slideOutLeft 1s both ease-in-out; }
#container.ng-enter .layer-two
{ animation: slideOutLeft 2s both ease-in-out; }
#container.ng-enter .layer-three
{ animation: slideOutLeft 3s both ease-in-out; }
</style>
<div ng-view id="container">
<ul id="photography-scene">
<li class="layer-one"
<img src="back.jpg" />
</li>
<li class="layer-two"
<img src="mid.jpg" />
</li>
<li class="layer-three"
<img src="front.jpg" />
</li>
</ul>
</div>
this is a JSFIDDLE of my code. In CSS, I defined different animations for elements .one and .two . If I remove these two classes, and leave the animation for the whole ngView, everything works

ng-enter not loading in when content loads angularjs

I have the following angularjs application which loads content from Instagram, however, on page load I would like to fade the loaded content in with a smooth transition.
I added {{ loadedClass }} to the main HTML tag but it doesn't seem to place ng-enter within it when it loads:
HTML
<script src="bower_components/angular/angular-animate.js"></script>
<section ng-controller="ShowImages as images" class="page {{ loadedClass }}" ng-view>
CSS
.page.ng-leave {
-webkit-animation: fadeOut 0.6s both ease-in;
-moz-animation: fadeOut 0.6s both ease-in;
animation: fadeOut 0.6s both ease-in;
}
/* line 697, ../sass/app.scss */
.page.ng-enter {
-webkit-animation: fadeIn 2s both ease-in;
-moz-animation: fadeIn 2s both ease-in;
animation: fadeIn 2s both ease-in;
}
**Controller
var app = angular.module('instafeed', ['ngAnimate']);
app.filter('getFirstCommentFrom',function(){
return function(arr, user){
for(var i=0;i<arr.length;i++)
{
if(arr[i].from.username==user)
return arr[i].text;
}
return '';
}
})
What am I doing wrong?
See here:
http://machinas.com/wip/machinas/instagramfeed/
I get this console error:
Error: [$injector:unpr] Unknown provider: $$qProvider <- $$q <- $animate <- $compile
http://errors.angularjs.org/1.2.22/$injector/unpr?p0=%24%24qProvider%20%3C-%20%24%24q%20%3C-%20%24animate%20%3C-%20%24compile
return new Error(message);
The class 'page' should go on each of your item, not the container:
<ul ng-show="layout == 'grid'" class="page grid">
<li></li>
</ul>
That is the ul who are entering and leaving when you change tabs, not the section
Knowing how events work, your ng-view is in the same level as ng-controller so when the event is emitted it doesn't "see" it. When events are emitted they are emmited to its parents.
I suggest the following in your HTML:
<section ng-controller="ShowImages as images" class="page {{ loadedClass }}" >
<div ng-view>
<!-- The rest of your code -->
</div>
</section>
EDIT
Sorry, I mislead you. I confused $emit with $broadcast.
EDIT 2
Looking at your HTML, you are not using ng-views correctly. The ng-views are supposed to be used together routes. That explains why the event is not firing. In your code, you are not loading a view at all.
EDIT 3
Look into animating the ng-cloak directive; you will be able to achieve just about the same result without views. What you are trying to do is not very complex and you seem to be starting out so I recommend skipping ng-view for now :)

How to make simple animation using ngAnimate

I am not able to understand how the ngAnimate works exactly. here is my doubt.
1) ngAnimate - only works on directives?
2) how to make ng-animate work without the directive
3) Any of above way, how to add call back after animation complete?
Because i see all the animation examples only with directives.
I have a small demo here, any one help me to animation both without directive and with directive approach to simply adding a class name as `fade'?
my CODE:
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2>Let me Fade</h2>
</div>
</div>
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2>Let me Fade</h2>
</div>
</div>
Demo to update
I am not able to understand how the ngAnimate works exactly. here is
my doubt.
ngAnimate is a module that provides support for animations in angular apps. There are two ways to make use of animations when ngAnimate is used: by using CSS and JavaScript. For CSS based animations, angularjs adds a class ng-enter/ng-leave whenever an element is shown/removed from 'view'. You simply need to play with these classes to make the animation work!
Prerequisite:
You would need to add the library for angular-animate
<script src="ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular-animate.js">
</script>
and include ngAnimate as the dependency in your myApp module.
var myApp = angular.module('myApp', ['ngAnimate']);
1) ngAnimate - only works on directives?
Yes. You cannot use ngAnimate without directive.
According to documentation, following directives are "animation aware":
ngRepeat, ngView, ngInclude, ngSwitch, ngIf, ngClass,
ngShow, ngHide, ngModel, ngMessages and ngMessage
2) how to make ng-animate work without the directive
You cannot!. Remember, even ng-click is a directive
3) Any of above way, how to add call back after animation complete?
Yes, You can add a callback after the animation is complete using the $animate service(which would usually be done in a custom directive) and use $animate.leave(element, [options]);
Have a look at this example for triggering events after the animation ends.
Finally, here is the updated demo you mentioned in question.
You may toggle a flag to true/false with each click on <h1> and make content inside <h2> hide/show based on flag.
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2 ng-if="flag" class="fade">Let me Fade</h2>
</div>
</div>
Also, you'd need to handle fade-effect with css
.fade.ng-enter {
transition:0.5s linear all;
opacity:0;
}
.fade.ng-enter.ng-enter-active {
opacity:1;
}
.fade.ng-leave {
transition:0.5s linear all;
opacity:1;
}
.fade.ng-leave.ng-leave-active {
opacity:0;
}
Hope it helps!
<div class="container" ng-app="myApp">
<div class="content" ng-controller="count">
<h1 ng-click="animate()">Click ME</h1>
<h2 ng-if="clicked" class="animate-if">Let me Fade</h2>
</div>
I added a variable named clicked which is set to true or false to animate the Let me Fade Text
var myApp = angular.module('myApp', []);
myApp.controller('count', function($scope) {
$scope.clicked=false;
$scope.animate = function () {
$scope.clicked=!$scope.clicked;
}
});
In this JS file upon clicking the click me button the variable clicked is set to true or false .
**
h2.fade {
opacity : 0;
transition: opacity 1s ease-in-out;
}
.animate-enter, .animate-leave {
transition: 500ms ease-in all;
position: relative;
display: block;
}
.animate-enter.animate-enter-active, .animate-leave {
left: 0;
}
.animate-leave.animate-leave-active, .animate-enter {
left: 500px;
}
**
Here in the css file i added css for the class animate which acts upon clicked variable if the variable is true it goes for animate-enter-active
otherwise it goes for leave-active

Resources