I have 2 html pages, welcome.html and login.html both of which are "inserted" into index.html dependending on the URL via an ngview attribute and router provider, as part of my AngularJS app.
An example of this can be found on the AngularJS home page under Wire up a Backend.
My question: Is there a way to animate the transition between welcome.html and login.html?
Angularjs 1.1.4 has now introduced the ng-animate directive to help animating different elements, in particular ng-view.
You can also watch the video about this new featue
UPDATE as of angularjs 1.2, the way animations work has changed drastically, most of it is now controlled with CSS, without having to setup javascript callbacks, etc.. You can check the updated tutorial on Year Of Moo. #dfsq pointed out in the comments a nice set of examples.
Check this code:
Javascript:
app.config( ["$routeProvider"], function($routeProvider){
$routeProvider.when("/part1", {"templateUrl" : "part1"});
$routeProvider.when("/part2", {"templateUrl" : "part2"});
$routeProvider.otherwise({"redirectTo":"/part1"});
}]
);
function HomeFragmentController($scope) {
$scope.$on("$routeChangeSuccess", function (scope, next, current) {
$scope.transitionState = "active"
});
}
CSS:
.fragmentWrapper {
overflow: hidden;
}
.fragment {
position: relative;
-moz-transition-property: left;
-o-transition-property: left;
-webkit-transition-property: left;
transition-property: left;
-moz-transition-duration: 0.1s;
-o-transition-duration: 0.1s;
-webkit-transition-duration: 0.1s;
transition-duration: 0.1s
}
.fragment:not(.active) {
left: 540px;
}
.fragment.active {
left: 0px;
}
Main page HTML:
<div class="fragmentWrapper" data-ng-view data-ng-controller="HomeFragmentController">
</div>
Partials HTML example:
<div id="part1" class="fragment {{transitionState}}">
</div>
I'm not sure about a way to do it directly with AngularJS but you could set the display to none for both welcome and login and animate the opacity with an directive once they are loaded.
I would do it some way like so. 2 Directives for fading in the content and fading it out when a link is clicked. The directive for fadeouts could simply animate a element with an unique ID or call a service which broadcasts the fadeout
Template:
<div class="tmplWrapper" onLoadFadeIn>
<a href="somewhere/else" fadeOut>
</div>
Directives:
angular
.directive('onLoadFadeIn', ['Fading', function('Fading') {
return function(scope, element, attrs) {
$(element).animate(...);
scope.$on('fading', function() {
$(element).animate(...);
});
}
}])
.directive('fadeOut', function() {
return function(scope, element, attrs) {
element.bind('fadeOut', function(e) {
Fading.fadeOut(e.target);
});
}
});
Service:
angular.factory('Fading', function() {
var news;
news.setActiveUnit = function() {
$rootScope.$broadcast('fadeOut');
};
return news;
})
I just have put together this code quickly so there may be some bugs :)
Try checking his post. It shows how to implement transitions between web pages using AngularJS's ngRoute and ngAnimate: How to Make iPhone-Style Web Page Transitions Using AngularJS & CSS
1.Install angular-animate
2.Add the animation effect to the class ng-enter for page entering animation and the class ng-leave for page exiting animation
for reference: this page has a free resource on angular view transition https://e21code.herokuapp.com/angularjs-page-transition/
Related
I've been trying to get AngularJS to fade in a tab pane when you select. I have it on jsfiddle
I have the following CSS to animate it with:
.tab-pane.active-add {
transition: opacity 10s;
opacity: 0
}
.tab-pane.active-add.active-add-active {
opacity: 1;
}
As you can see when you go to the fiddle it does not fade in when you change a tab.
use a .css like this:
.tab-pane.active:not(.show) {
opacity: 0;
}
.tab-pane.active{
opacity:1;
transition: opacity 2s;
}
Then declare a new variable
$scope.active_show=0;
Now use ng-class to add the two classes
<div class="tab-pane" ng-class="{active: active === $index,
show: active_show === $index}"
ng-repeat="tab in tabs">
{{tab.content}}
</div>
And change your function like
$scope.setActive = function(index) {
$scope.active = index;
setTimeout(()=>{
$scope.active_show=index;
$scope.$apply();
})
}
The idea is that your div, when active has first a class .active and in a new cycle -it's the function of setTimeOut- the class is .active.show
your fork jsfiddle
NOTE: I use the use of .show/not(.show) because it's the way, e.g. bootstrap, use
NOTE2: I imagine you're work in an old project, AngularJs is a bit old and soon you Sooner rather than later should change to Angular
http://www.chooseyourtelescope.com/ (>> Please watch it on a minimum 15'' screen, the site is not entirely responsive yet and you wont see what I'm talking about)
When you hover the buttons (moon, planet, etc...) it changes the background. But the transition is buggy on Chrome (image0>blank>image1). And worknig on IE11 but sometimes with a lag. I didn t try with the other browsers.
How to make a smooth transition?
A quick fade Image0>image1, not image0>transition color>image1
Here is the code for the MOON button. Thats the same with the others.
(I don't know anything about Javascript. I found the script below on Stackoverflow.)
HTML
<div class="top-logos-home" id="top-logos-moon-front"><img src="moon-logo.png" alt="MOON"></div>
CSS
.image-home {
position: absolute;
width: 100%;
height: 100%;
background-image: url(Frontpage.jpg);
background-size: cover;
display:inline;
top:0;
}
JAVASCRIPT
jQuery(function(){
var $body = $('.image-home');
$('#top-logos-moon-front').hover(function(){
$body.css('background-image', 'url("Frontpage-moon.jpg")')
}, function() {
$body.css('background-image', '')
})
})
You need to change just your script code if you want smooth transtion.
jQuery(function(){
var $body = $('.image-home');
$('#top-logos-moon-front').hover(function(){
$body.fadeOut('slow',function(){
$body.css('background-image', 'url("Frontpage-moon.jpg")').fadeIn('slow');
});
}, function() {
$body.css('background-image', '')
})
})
If you want to do best solution for this you need follow the steps below.
Firstly you need to defined your path of images in the js with the below code.
var imgs = [
'http://i.imgur.com/DwLjYhh.jpg',
'http://i.imgur.com/gAlqfUU.jpg'
];
After this step, you need to add new attiribute your buttons like data-id.
<div class="top-logos-home" id="top-logos-moon-front" data-id='0'>
<img src="button_image_jpg" alt="MOON">
</div>
When you defined all variables, you need to detect the hover with your current code and choose the right image that is in imgs array for your background.
jQuery(function(){
var $body = $('.image-home');
$('#top-logos-moon-front').hover(function(){
$body.fadeOut('slow',function(){
//fade out slowly element and after change the style of inner elements then fade in slowly.
$body.css('background-image','url('+imgs[$(this).attr('data-id')]+')').fadeIn('slow');
});
});
});
In my personal opinion; Image transitions shouldn't manage in this way. Create different element for each planets. When user click the button, planets slip and overlapping. You can see a demo in the below code.
http://codepen.io/thegeek/pen/GDwCa
I found a solution by using the opacity property. Now its working perfectly.
HTML
<img id="background-moon-front" class="hover-backgrounds" src="Frontpage-moon.jpg" />
CSS
.hover-backgrounds {
opacity:0;
transition: opacity 0.6s linear;
top:0;
position:absolute;
background-size: 100%;
}
JAVASCRIPT
$(document).ready(function (e) {
$("#top-logos-lune-front").hover(function (e) {
$("#background-moon-front").css("opacity", "1");
}, function() {
$("#background-moon-front").css("opacity", "0")
})
});
I'm trying to fade out a div and then show a new div but my code is broken. How can I fix? The fade-out animation works but the showManagement div does not appear.
HTML
<div ng-hide="hidden" ng-class="{fade: startFade}">
<p>this is start content that should be faded</p>
</div>
<div class="showManagement" ng-show="showManagement">
<p>this is the new content to be displayed once the fade is complete.</p>
</div>
JS
$scope.getManagement = function () {
$scope.startFade = true;
$timeout(function(){
$scope.hidden = true;
}, 2000);
// this is the part that doesn't display
$scope.showManagement = true;
};
CSS
.fade{
transition: opacity 3s;
opacity: 0;
}
Since you didn't provide your controller and didn't show where you call the function getManagement(), I'll assume that you want all the fade-out fade-in events show within 2 seconds after angular loaded.
Here's an example on CodePen for how you can achieve your goal with your approach.
And here's the code:
HTML
<body ng-app="myApp">
<div class="wrapper" ng-controller="MainCtrl">
<div ng-class="{fade: startFade}">
<p>this is start content that should be faded</p>
</div>
<div ng-class="{hideManagement: hideManagement, showManagement: showManagement}">
<p>this is the new content to be displayed once the fade is complete.</p>
</div>
</div>
</body>
CSS
.fade{
transition: opacity 3s;
opacity: 0;
}
.hideManagement {
opacity: 0;
}
.showManagement {
transition: opacity 3s 3s;
opacity: 1;
}
JS
angular
.module('myApp', [])
.controller('MainCtrl', ['$scope', '$timeout', function($scope, $timeout) {
$scope.startFade = false;
$scope.showManagement = false;
$scope.hideManagement = true;
$timeout(function(){
$scope.startFade = true;
$scope.showManagement = true;
$scope.hideManagement = false;
}, 2000);
}]);
A few things you have to keep in mind:
You cannot animate your display: none; and display: block; with CSS3 transition. This is the reason why ng-hide in your .showManagement is not showing with transition effect. You should keep using opacity to achieve this goal, just like you did in ng-class="{fade: startFade}"
Initialize your state at the beginning of your Angular controller. In the example your provide, it's a little bit confusing how you set your $scope.showManagement, $scope.hidden, and $scope.startFade. Once you setup your initial state like the example I provide, it would be more clear that what kind of states change you should make in the function, whether it's in a $timeout callback or some other functions trigger by other events
To make .showManagement fade-in right after the first <div> finishing it's fade-out effect, you may set the delay in css transition.
If you are doing more complex animation, you should try leveraging on ngAnimate service. With ngAnimate, you can get rid of those ng-class in this example, and simply binding your animation rules with .ng-enter, .ng-enter-active, .ng-hide, .ng-hide-active, which are automatically bind to your elements by Angular. Here's the official documentation for ngAnimate.
Is there a way to make a menu that is closed by toggleClass() be closed automatically after refreshing the page?
The button that calls toggleClass() works perfectly. The session also remembers if the menu is hidden, so it performs the closing animation upon refresh. Is there an easy way to have the menu hidden when refreshed instead of performing the animation?
For further clarification, here is a quick video I took of the issue:
initialize: function()
{
if(sessionStorage.getItem('sidebar.open') == 'false')
{
this.toggle();
}
},
toggle: function()
{
var self = this;
$(this.sidebarEl).toggleClass('active');
_.each(this.contentEl, function(el)
{
$(el).toggleClass('active');
});
sessionStorage.setItem('sidebar.open',
$(this.sidebarEl).hasClass('active'));
},
I'm assuming the transition is a CSS transition, right? That's why you're only changing the class...
Think about maybe canceling the transition, and then re-appending it.
CSS
.notransition { /*class to cancel transition*/
-webkit-transition: none !important;
-moz-transition: none !important;
-o-transition: none !important;
-ms-transition: none !important;
transition: none !important;
}
HTML
<div class="menu nontransition">...</div> <!-- when the page is loaded, use nontransition... -->
JS
initialize: function()
{
if(sessionStorage.getItem('sidebar.open') == 'false')
{
this.toggle();
}
$(this.sidebarEl).removeClass("nontransition") // Then, delete nontransition, and allow the transition to work
},
I have a list which I iterate over by using ng-repeat: and the user can interact with thte list items by using up-arrow and down-arrow icons and on click of them i simply change the order of the element in the "list" this is what angular suggests change the model and the changes automatically reflect in the view.
<div ng-repeat="item in list">
{{item.name}}
<div class="icon-up-arrow" ng-click="moveUp($index);"></div>
<div class="icon-down-arrow" ng-click="moveDown($index);"></div>
</div>
Logic in moveUp:-
$scope.moveUp= function(position){
var temp=list[position-1];
list[position-1]=list[position];
list[position=temp];
};
the above code works completely fine and similar is the logic for shifting the item down. But the problem that i want to resolve is how do i put animation? I know angular takes care of binding view and model on its own but is there any way to put in animation as the view is updated on pressing up an down arrow icons?
Following on from Marcel's comment: in AngularJS 1.2 you don't need to use the ng-animate directive. Instead:
Includeangular-animate[-min].js.
Make your module depend on ngAnimate.
Define your transitions in CSS using classes like .ng-enter and .ng-enter-active.
Use ng-repeat as you normally would.
HTML:
<div ng-app="foo">
<!-- Set up controllers etc, and then: -->
<ul>
<li ng-repeat="item in items">{{item}}</li>
</ul>
JavaScript:
angular.module('foo', ['ngAnimate']);
// controllers not shown
CSS:
li {
opacity: 1;
}
li.ng-enter {
-webkit-transition: 1s;
transition: 1s;
opacity: 0;
}
li.ng-enter-active {
opacity: 1;
}
Demo in (someone else's) Plunker.
See the docs for $animate for details on the progression through the various CSS classes.
Check this link http://www.nganimate.org/
You need to declare the ng-animate attribute to an element that have another directive that changes the DOM
div ng-repeat="item in itens" ng-animate="{enter: 'animate-enter', leave: 'animate-leave'}"
You need to add css transitions or animation.
.animate-enter {
-webkit-transition: 1s linear all; /* Chrome */
transition: 1s linear all;
opacity: 0;
}
.animate-enter.animate-enter-active {
opacity: 1;
}
You can check plnkr example here: http://plnkr.co/edit/VfWsyg9d7xROoiW9HHRM
Complementing the last answer, there is the ng-move class for animations when order is changed:
li {
opacity: 1;
}
li.ng-move {
-webkit-transition: 1s;
transition: 1s;
opacity: 0;
}
li.ng-move-active {
opacity: 1;
}
Last documentation here.
If you don’t wish to use ‘ngAnimate’ module because of reduce the plugins count, you can archive the simple transition effect by using ng-init and custom directives.
<li ng-repeat="item in items" class="item" item-init>{{item.name}}</li>
.item{
opacity:0;
-webkit-transition: all linear 300ms;
transition: all linear 300ms;
}
.item.visible{
opacity:1;
}
myApp.directive('itemInit', function ($compile) {
return function (scope, element, attrs) {
scope.initItem(element);
};
});
In you controller
$scope.initItem = function(el){
$timeout(function(){
angular.element(el).addClass('visible');
},0);
}