可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
i'm using ng-animate to slide the app views, so each route slides own view , this is my simple code:
html:
<div ng-view ng-animate class="slide"></div>
css:
/*Animations*/
.slide{
left:0;
}
.slide.ng-enter{
transition:0.15s linear all;
position:fixed;
z-index:inherit;
left:-100%;
height:inherit;
}
.slide.ng-leave{
transition:0.15s linear all;
position:fixed;
z-index:9999;
right:0;
}
.slide.ng-leave-active{
transition:0.15s linear all;
position:fixed;
right:-100%;
left:100%;
}
.slide.ng-enter-active{
transition:0.15s linear all;
left:0;
position:relative;
}
Now, i'm wondering , is there anyway to exclude the home page (main "/" route) from sliding?
In other terms: Any way to exclude a route from ng-animate?
回答1:
That's what ng-class
is for.
You can set a application-wide variable $rootScope.path whenever path changes.
app.run(function ($rootScope, $location) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
$rootScope.path = $location.path();
});
});
Then, you decide to set your animation class by that variable
If you want to set class slide
only if path is not /
, do like this
<div ng-view ng-class="{slide: path !== '/' }"></div>
By doing this way, you don't need to touch any of your controller.
Full demo is here, http://plnkr.co/edit/rmu8oc7ycKzRaA2zv5JN?p=preview
By the way, this uses currant angularJS version, 1.2.7
------- Edit (animate after visit main page) ------
app.run(function ($rootScope, $location) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
if (!$location.path().match(/^\/?$/) && !$rootScope.mainVisitedOnce) {
$rootScope.mainVisitedOnce = true;
}
});
});
and
<div ng-view ng-class="{slide: mainVisitedOnce }"></div>
http://plnkr.co/edit/QpDFkdKH1kk6ZXy07G5X?p=preview
回答2:
Demo http://plnkr.co/edit/sMUM48?p=preview
Explain
No need to create separate controller, directive or change any business logic. Just use .animation
method to add conditional animation to .slide
.
Listen to $routeChangeSuccess
event on $rootScope
. This is event will be triggered before animation start, so you have time to set toRoot
and fromRoot
flag accordingly. If target view is not a "/" view, a enable-animation
class will be added to ng-view
element, so css transition defined will be performed.
If target view if a "/" view, no animation will be performed.
HTML
<ng-view class="slide"></ng-view>
CSS
.slide {
position: absolute;
top: 0;
width: 100%;
}
.slide div {
margin: 10px;
background: red;
}
.slide.enable-animation.ng-enter,
.slide.enable-animation.ng-leave {
transition: all 10s;
z-index: 1;
}
.slide.enable-animation.ng-enter {
left: -100%;
opacity: 0;
}
.slide.enable-animation.ng-enter.ng-enter-active,
.slide.enable-animation.ng-leave {
left: 0;
opacity: 1;
}
.slide.enable-animation.ng-leave.ng-leave-active {
left: 100%;
opacity: 0;
}
JavaScript
app.animation('.slide', function($rootScope, $animate) {
var toRoot = false;
var fromRoot = false;
$rootScope.$on('$routeChangeSuccess', function(event, current, old) {
toRoot = (current.$$route.originalPath === '/');
fromRoot = (old.$$route.originalPath === '/');
});
return {
enter: function(element, done) {
if (!toRoot) {
element.addClass('enable-animation');
}
done();
},
leave: function(element, done) {
if (!fromRoot) {
element.addClass('enable-animation');
done();
} else {
// set 1000ms timeout to sync with CSS animation
// otherwise leaving ng-view element will be removed before entering ng-view is in position
setTimeout(done, 1000);
}
}
}
});
Update 1
If you just want to exclude a route only when the first time app loads, you basically don't have to do anything, just define your css animation like normal. The first loaded route won't trigger any animation.
Demo http://plnkr.co/edit/uRZyZA?p=preview
回答3:
Borrowing from @allenhwkim, get path in your rootScope.
app.run(function ($rootScope, $location) {
$rootScope.$on("$locationChangeStart", function (event, next, current) {
$rootScope.path = $location.path();
});
});
Then have this as your element:
<div ng-view ng-animate ng-class="{slide: path !== '/' }"></div>
.slide
will be added to your container element when the path being loaded isn't /
.
Here's a working Plunker.
回答4:
Why don't you simply add a root class like class="not-animated"
and class="animated"
to the controllers you don't want or want to be animated?
In this way you could use the .not-animated
and .animated
class to play with your animation in different controllers.
You can set your controller like this:
<body ng-controller="MainCtrl" ng-class='isAnimated'>
<div ng-controller="FirstCtrl" ng-class='isAnimated'>Foo</div>
<div ng-controller="SecondCtrl" ng-class='isAnimated'>Bar</div>
</body>
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.isAnimated = 'not-animated';
});
app.controller('SecondCtrl', function($scope) {
$scope.isAnimated = 'animated';
});
This will result in:
<body ng-controller="MainCtrl" ng-class="isAnimated" class="ng-scope not-animated">
<p class="ng-binding">Hello World!</p>
<div ng-controller="FirstCtrl" ng-class="isAnimated" class="ng-scope not-animated">Foo</div>
<div ng-controller="SecondCtrl" ng-class="isAnimated" class="ng-scope animated">Bar</div>
</body>
DEMO
回答5:
You can build a controller that listens for route changes and sets a class accordingly. You will then be able to target the correct animation using CSS.
<body ng-controller="TranisitionCtrl" ng-class="currentRoute">
<div ng-view ng-animate></div>
</body>
app.controller('TranisitionCtrl', function($scope) {
$scope.$on('$routeChangeStart', function(ev, next, current) {
$scope.currentRoute = current.name;
});
});
Please note $routeChangeStart has been changed to $locationChangeStart for more recent versions of angular.
I've answered another similar question here Two different animations for route changes
回答6:
One way to exclude a specific route from the animation is to use a JS animation wrapper that will take over setting of the animation class for your ng-view
. You need one additional class to handle the non-animated ng-leave
when you are going back to the non-animated route.
Here is a sample JS wrapper that check for a custom animate
attribute in your route to decide if a route is animated or not:
app.animation('.slider', function($log, $route) {
return {
//call done when the animation is over
enter : function(element, done) {
if ($route.current.animate) {
element.addClass("slide ng-enter");
}
done();
},
leave : function(element, done) {
if ($route.current.animate) {
element.addClass("slide ng-leave");
} else {
// Need to add non-animated version of ng-leave
element.addClass("slide ng-leave-noanimation");
}
done();
}
}
});
Here is the working plunker:
http://plnkr.co/edit/ldCy9Cfz2lJWNuLzDIbp?p=preview
回答7:
As far as i understand you, what you want is, that no animation happens if the user hits your site. But after that the animations should happen all the time. This is the shortest solution i know:
Use the module run
method to disable all animations:
app.run(function($animate){
$animate.enabled(false);
});
In your controller that is bound to /
reenable the animations, but delayed for one digest cycle:
.controller('rootController', function($timeout, $animate){
$timeout(function(){
$animate.enabled(true);
});
})