Angular js - slide views but not home page - ng-animate

雨燕双飞 提交于 2019-12-09 16:28:33

问题


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


来源:https://stackoverflow.com/questions/20869011/angular-js-slide-views-but-not-home-page-ng-animate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!