I'm encountering some strange behavior in one of my web apps when using Angular's routeProvider as a template engine. Although it works, it doesn't make sense to me why it works.
Whats happening is that during transitions from page to page (mostly in safari/mobile safari) you will see the page you're transitioning to flicker in the front of view before transitioning in. How I fixed this problem is just by adding a slash to the end of the href's url, ex:href="#/home/" instead of href="#/home . Does anyone out there know why adding a "/" to the url would fix such a problem?
I set up the routeProvider like this:
.config(function($routeProvider) {
$routeProvider.when('/home', {
controller : 'HomeCtrl',
templateUrl : './home.html'
}).when('/pageTwo', {
controller : 'twoCtrl',
templateUrl : './pageTwo.html'
}).otherwise({
redirectTo: '/home'
});
})
My html like this:
<ul id="nav">
<li>
HOME
</li>
<li>
TWO
</li>
</ul>
and css like this:
.view-animate-container {
position:relative;
width: 100%;
height: 100%;
}
.view-animate {
position: absolute;
width: 100%;
height: 100%;
-webkit-perspective: 1000;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.view-animate.ng-enter, .view-animate.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
-o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s;
}
.view-animate.ng-enter {
opacity:0;
-webkit-transform: translate3d(20%,0,0);
transform: translate3d(20%, 0, 0);
}
.view-animate.ng-enter.ng-enter-active {
display: block;
-webkit-transform: translate3d(0,0,0);
transform: translate3d(0, 0, 0);
opacity:1;
}
.view-animate.ng-leave.ng-leave-active {
-webkit-transform: translate3d(-20%,0,0);
transform: translate3d(-20%, 0, 0);
opacity:0;
}
Is there a reason why you link to the hash instead of the route itself?
Have you tried changing your links to Home instead of href="#/home" ?
Angular will manage the hash for you, (or not, if your browser supports pushState).
Related
An element has class slider-item:
.slider-item{
transform: translateY(100%);
transition: transform 100s ease;
transition-delay: 800ms;
}
When i click on a button ,i want the element to transition between translateY(-100%) and translateY(0).
I add classes prev-version and next by javascript respectively:
.slider-item.prev-version{
transform: translateY(-100%);
transition: none;
}
.slider-item.next{
transform: translateY(0);
transition: transform 100s ease;
transition-delay: 800ms;
}
But i see transition happens between translateY(100%) and translateY(0). next class overrides transform: translateY(-100%); in prev-version class. Please help me what should i do?
The best thing to try would probably be to use Vanilla JavaScript, jQuery, or some other type of framework to directly edit and change the CSS attributes.
So for example the jQuery version would be:
$("#slider-item.next").css("transform:translateY(0)");
Keep in mind you would need to add logic so that if the attribute was 100 it would change it back to 0 and then if it was 0 it would change it back to 100.
w3schools.com/jquery/jquery_css.asp
I might didn't understand your question but seems that you can use css animation for this:
document.querySelector('button').addEventListener('click', function () { document.querySelector('.slider-item').classList.add('example'); });
button {position: fixed; bottom: 10vh} /* just for demo */
.slider-item{
transform: translateY(100%);
transition: transform 100s ease;
transition-delay: 800ms;
}
.example {
animation: example 3s ease-in-out;
}
#keyframes example {
from {transform: translateY(-100%);}
to { transform: translateY(100%);} /* should be the same as the value declared initial on .slider-item */
}
<div class="slider-item">Slider Item</div>
<button>Click</button>
I tried to use ng-animate i included in my controller
app = angular.module('Packs', ['ngAnimate']);
This is my style:
<style>
.animate-in {
opacity: 0;
max-height: 0;
overflow: hidden;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
transition: all 0.5s;
}
.animate-out{
opacity: 1;
max-height: 200px;
-webkit-transition: all 0.5s;
-moz-transition: all 0.5s;
transition: all 0.5s;
}
</style>
This is the html that is not working, well, it does work, just i had to do it toggling classes manually, i wanted to use ng-animate
<div ng-click="toggle('pack1')">
<div class="text"
ng-class="{'animate-in' : !displays.pack1,
'animate-out' : displays.pack1}">
Some text to toggle
</div>
</div>
Yes, use ng-show = "displays.pack1" on your text and then use the special classes ng-hide/ng-hide-active, see example in the documentation
Here is a jsfiddle that shows a toggle with opacity and height: http://jsfiddle.net/1djeqjfm/1/
.box.ng-hide { opacity:0; }
.box.ng-hide-active { opacity:1; }
(Or use ng-if and its classes ng-enter/ng-leave)
This is my html:
<html>
<head></head>
<body>
<form role="form" ng-if="on" ng-animate="{enter: 'animate-enter', leave: 'animate-leave'}">
...stuff...
</form>
</body>
</html>
This is my model:
$scope.on = false;
//attaching this function to the window so i can call it from the console
window.switchOn = function() {
$scope.$apply(function() {
$scope.on = !$scope.on
});
}
This is my CSS:
.animate-enter {
-webkit-transition: 1s linear all; /* Chrome */
transition: 1s linear all;
opacity: 0;
}
.animate-enter.animate-enter-active {
opacity: 1;
}
I've also added the ngAnimate inclusion to my app controller:
angular.module('app', [..., 'ngAnimate'])...
The purpose of this is to toggle the form from the console. According to the ngAnimate docs, the form should animate into appearance (I'm using Chrome). But it isn't. I've included the angular-animate file. I can see it in the loaded sources. What am i doing wrong?
Step One: Make sure you are including the ng-animate module. Here are the steps from the docs:
Animations are not available unless you include the ngAnimate module as a dependency within your application.
First include angular-animate.js in your HTML:
<script src="angular.js">
<script src="angular-animate.js">
You can download this file from the following places:
Google CDN
//ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-animate.js
Bower
bower install angular-animate#X.Y.Z
code.angularjs.org
//code.angularjs.org/X.Y.Z/angular-animate.js"
where X.Y.Z is the AngularJS version you are running.
Then load the module in your application by adding it as a dependent module:
angular.module('app', ['ngAnimate']);
With that you're ready to get started!
Step Two:
Your CSS needs to have a .ng-enter class:
.reveal-animation.ng-enter {
-webkit-animation: enter_sequence 1s linear; /* Safari/Chrome */
animation: enter_sequence 1s linear; /* IE10+ and Future Browsers */
}
#-webkit-keyframes enter_sequence {
from { opacity:0; }
to { opacity:1; }
}
#keyframes enter_sequence {
from { opacity:0; }
to { opacity:1; }
}
And your html simply has to have the class:
class="reveal-animation"
http://jsfiddle.net/bpR66/
If pre version 1.2
Your CSS needs to have -setup, and -setup.-start classes:
.animate-enter-setup {
-webkit-transition:all linear 1s;
-moz-transition:all linear 1s;
-ms-transition:all linear 1s;
-o-transition:all linear 1s;
transition:all linear 1s;
}
.animate-enter-setup {
max-height: 0;
opacity:0;
}
.animate-enter-setup.animate-enter-start {
opacity:1;
min-height: 20px;
}
Here is a fiddle I modified to show an example (not using a form, but should demonstrate): http://jsfiddle.net/xv5ry/1/
I am trying to toggle between two animation classes within my ng-view. This is how I have my ng-view setup in my html:
<div id="animation-container" class="view-animate-container">
<div id="ng-view" ng-view class="view-animate"></div>
</div>
And here is the css for my first animation
.view-animate.ng-enter, .view-animate.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.8s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.8s;
display:block;
position:absolute;
top:0;
left:0;
}
.view-animate.ng-enter {
-webkit-transform: translate3d(100%, 0, 0);
}
.view-animate.ng-enter.ng-enter-active {
-webkit-transform: translate3d(0, 0, 0);
}
.view-animate.ng-leave.ng-leave-active {
-webkit-transform: translate3d(-100%, 0, 0);
}
2nd animation:
.view-leave.ng-enter, .view-leave.ng-leave {
-webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.8s;
-moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.8s;
-o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.8s;
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.8s;
display:block;
position:absolute;
top:0;
left:0;
}
.view-leave.ng-enter {
opacity:0;
-webkit-transform: translate3d(-100%, 0, 0);
}
.view-leave.ng-enter.ng-enter-active {
opacity:1;
-webkit-transform: translate3d(0, 0, 0);
}
.view-leave.ng-leave.ng-leave-active {
opacity:0;
-webkit-transform: translate3d(100%, 0, 0);
}
All I'm trying to do is change the class from view-enter to view-leave when the back button is clicked.
<a id="back-btn" class="btn back" href="javascript:history.back()">BACK</a>
This Jquery code I wrote almost got the job done, but not 100%:
$("#back-btn").click(function(){
$("#ng-view").attr('class','view-leave');
});
It seemed to animate the leaving container in the right direction, but not the entering container. So I'm looking for a simple solution to what seems like a simple problem.
You don't even need jQuery for this, you can use Angular's ng-class attribute. Add an ng-click to your back button which calls a function inside your controller. Something like this:
In your HTML:
<div id="animation-container" class="view-animate-container">
<div id="ng-view" ng-view class="view-animate" ng-class="animationClass"></div>
</div>
<a class="btn back" href="javascript:history.back()" ng-click="toggleAnimation()">BACK</a>
In your Controller:
$scope.animationClass = "view-enter";
$scope.toggleAnimation = function() {
if ($scope.animationClass === "view-enter") {
$scope.animationClass = "view-leave";
} else if ($scope.animationClass === "view-leave") {
$scope.animationClass = "view-enter";
}
};
I found a different way with the new $routeChangeStart event.
This solution saves history to check if the next page is actually the previous page.
Place this in your controlller:
$scope.backward = false;
$scope.history = [];
$scope.$on('$routeChangeStart', function(next, current) {
var previous = $scope.history[$scope.history.length - 2];
if (previous && current.originalPath === previous.originalPath) {
$scope.backward = true;
$scope.history.pop();
} else {
$scope.backward = false;
$scope.history.push(current);
}
});
Then use a container around your ng-view with an ng-class reacting to the $scope.backward.
<div ng-class="{'backward': backward}">
<ng-view class="view-animate">
</div>
And have two CSS animations. The forward on .view-animate or whatever class you use for your ng-view. And the backward on .backward .view-animate.
Just for anyone else that might be looking for a simple solution to this question, expanding off #muenchdo answer. I set a timeout to revert to the previous animation after the transition was over.
like this:
$scope.animationClass = "view-enter";
$scope.toggleAnimation = function() {
$scope.animationClass = "view-leave";
$timeout(function() {
$scope.animationClass = "view-enter";
}, 350);
}
This was the simplest way I could find out there, hopefully this helps someone out there that is looking for a simple solution to what seems like simple functionality.
I try to animate the change of a ng-view div in AngularJS.
So my div inside my index.html file looks like:
<div ng-view></div>
I have another html-file (view1.html) with just divs inside.
My app.js with the routing looks like:
app.config(function($routeProvider) {
$routeProvider
.when('/sites/:templateID',
{
controller: 'simpleController',
templateUrl:'templates/question.html'
})
});
I am changing the path with a click on a button, and call this:
$location.path("/sites/" + nextID);
The URL changes of the site, and only the ng-view-div gets updated. But when i am applying a ng-animation to it:
<div class="content" data-ng-view ng-animate="{enter: 'animate-enter', leave: 'animate-leave'}"></div>
It doesn't work. I included AngularJS 1.2.5, the animate-js file inside my index.html and also my CSS:
.animate-enter, .animate-leave {
-webkit-transition:all 2s ease;
-moz-transition:all 2s ease;
-o-transition:all 2s ease;
transition:all 2s ease;
}
.animate-enter {
left: -100%;
}
.animate-enter.animate-enter-active {
left: 0;
}
.animate-leave {
left: 0;
}
.animate-leave.animate-leave-active {
left: 100%;
}
Is there a way to animate the ng-view change through route-(URL)-changing?
ng-view can work with animation. In fact there is official example of it. Check out this link.
Also remember that you also need to declare ngAnimate dependency for it to work:
var app = angular.module('App', [
'ngRoute',
'ngAnimate'
]);
HTML
<div class="content">
<div class="question" ng-view></div>
</div>
Class .question defines CSS animation:
.question.ng-enter,
.question.ng-leave {
-webkit-transition: all 1s ease;
-moz-transition: all 1s ease;
-o-transition: all 1s ease;
transition: all 1s ease;
}
Your modified demo Plunker.
Mini-project
I also created a little project demonstrating different ngView animations. Check it out this page.
There are a few changes to the CSS rules with Angular Animation 1.2+. ng-animate directive is no longer used so AngularJS now changes the class of the element based on events, such as hide, show, etc.
You can define these like so in your CSS:
.toggle {
-webkit-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
-moz-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
-ms-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
-o-transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
transition: all 0 cubic-bezier(0.25, 0.46, 0.45, 0.94);
/* easeOutQuad */
-webkit-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
-moz-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
-ms-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
-o-transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
transition-timing-function: cubic-bezier(0.25, 0.46, 0.45, 0.94);
/* easeOutQuad */
}
.toggle.ng-enter {
opacity: 0;
transition-duration: 250ms;
-webkit-transition-duration: 250ms;
}
.toggle.ng-enter-active {
opacity: 1;
}
.toggle.ng-leave {
opacity: 1;
transition-duration: 250ms;
-webkit-transition-duration: 250ms;
}
.toggle.ng-leave-active {
opacity: 0;
}
.toggle.ng-hide-add {
transition-duration: 250ms;
-webkit-transition-duration: 250ms;
opacity: 1;
}
.toggle.ng-hide-add.ng-hide-add-active {
opacity: 0;
}
.toggle.ng-hide-remove {
transition-duration: 250ms;
-webkit-transition-duration: 250ms;
display: block !important;
opacity: 0;
}
.toggle.ng-hide-remove.ng-hide-remove-active {
opacity: 1;
}
That way when you have your HTML element you really only have to define the class="toggle" for example. When your app runs Angular will append the classes appropriately.
Here is a good resource for different animation techniques by Augus
And here is a break down of the changes in AngularJS Animations
In 1.2+ you no longer need the directive, the css notation has changed aswell.
The 1.2.5 way of doing it is as follows:
Give your View a class:
<div data-ng-view class="mainview-animation"></div>
Add the following dependency:
/**
* Main Application & Dependencies
* #type {*}
*/
var mainApp = angular.module('app', [
// Angular modules
'ngRoute',
'ngAnimate'
]);
Then add the following CSS:
/*
The animate class is apart of the element and the ng-enter class
is attached to the element once the enter animation event is triggered
*/
.mainview-animation.ng-enter {
-webkit-transition: .3s linear all; /* Safari/Chrome */
-moz-transition: .3s linear all; /* Firefox */
-o-transition: .3s linear all; /* Opera */
transition: .3s linear all; /* IE10+ and Future Browsers */
}
/**
* Pre animation -> enter
*/
.mainview-animation.ng-enter{
/* The animation preparation code */
opacity: 0;
}
/**
* Post animation -> enter
*/
.mainview-animation.ng-enter.ng-enter-active {
/* The animation code itself */
opacity: 1;
}
Just to add to the accepted answer it is necessary to either define position: absolute or display: block to .ng-enter and .ng-leave. I struggled with this for a while when trying to fade in ng-view on route change and didn't want to use absolute positioning. Example without browser prefixes for transition:
//add animate class to ng-view
//css
.animate.ng-leave, .animate.ng-enter {
transition: 1s cubic-bezier(0.5, 0.1, 0.25, 1) all;
}
.animate.ng-enter, .animate.ng-leave.ng-leave-active {
opacity: 0;
display: block;
}
.animate.ng-leave, .animate.ng-enter.ng-enter-active {
opacity: 1;
display: block;
}
For my specific situation I removed the transition from ng-leave so there wouldn't be overlap of elements which would cause one to be pushed down due to block display.