8

我正在使用ng-animate来滑动应用程序视图,所以每条路线都会滑动自己的视图,这是我的简单代码:

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

现在,我想知道,is there anyway to exclude the home page (main "/" route) from sliding?

换句话说:有什么方法可以从 ng-animate 中排除路由?

4

7 回答 7

7

ng-class就是为了。

每当路径更改时,您都可以设置应用程序范围的变量 $rootScope.path。

app.run(function ($rootScope, $location) {
  $rootScope.$on("$locationChangeStart", function (event, next, current) {
    $rootScope.path = $location.path();
  });
});

然后,您决定通过该变量设置动画类

如果您只想slide在路径不是的情况下设置类/,请这样做

<div ng-view ng-class="{slide: path !== '/' }"></div>

通过这样做,您无需触摸任何控制器。

完整的演示在这里,http ://plnkr.co/edit/rmu8oc7ycKzRaA2zv5JN?p=preview

顺便说一句,这使用 currant angularJS 版本,1.2.7

------- 编辑(访问主页后动画)------

app.run(function ($rootScope, $location) {
  $rootScope.$on("$locationChangeStart", function (event, next, current) {
    if (!$location.path().match(/^\/?$/) && !$rootScope.mainVisitedOnce) {
      $rootScope.mainVisitedOnce = true;
    }
  });
});

<div ng-view ng-class="{slide: mainVisitedOnce }"></div>

http://plnkr.co/edit/QpDFkdKH1kk6ZXy07G5X?p=preview

于 2014-01-10T18:26:19.963 回答
4

演示http://plnkr.co/edit/sMUM48?p=preview

解释

无需创建单独的控制器、指令或更改任何业务逻辑。只需使用.animation方法将条件动画添加到.slide.

在 上收听$routeChangeSuccess事件$rootScope。这是事件将在动画开始之前触发,因此您有时间相应地设置toRootfromRoot标记。如果目标视图不是"/" 视图,则会在元素中添加一个enable-animationng-view,因此将执行定义的 css 转换。

如果目标视图是“/”视图,则不会执行动画。

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

更新 1

如果您只想在第一次加载应用程序时排除路由,您基本上不必做任何事情,只需像平常一样定义您的 css 动画。第一个加载的路线不会触发任何动画。

演示http://plnkr.co/edit/uRZyZA?p=preview

于 2014-01-11T06:14:15.820 回答
2

借用@allenhwkim,在你的 rootScope 中获取路径。

app.run(function ($rootScope, $location) {
  $rootScope.$on("$locationChangeStart", function (event, next, current) {
    $rootScope.path = $location.path();
  });
});

然后将其作为您的元素:

<div ng-view ng-animate ng-class="{slide: path !== '/' }"></div>

.slide当加载的路径不是 时,将被添加到您的容器元素中/

这是一个正在工作的 Plunker

于 2014-01-11T03:59:58.983 回答
1

为什么不简单地添加一个根类,例如class="not-animated"class="animated"到您不想要或想要动画的控制器?
通过这种方式,您可以使用.not-animatedand.animated类在不同的控制器中播放动画。

你可以像这样设置你的控制器:

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

这将导致:

<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>

演示

于 2014-01-10T14:25:26.113 回答
1

您可以构建一个控制器来侦听路由更改并相应地设置一个类。然后,您将能够使用 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;
  });
}); 

请注意 $routeChangeStart 已更改为 $locationChangeStart 以获取更新版本的 Angular。

我在这里回答了另一个类似的问题 路线更改的两个不同动画

于 2014-01-10T16:32:17.090 回答
1

从动画中排除特定路线的一种方法是使用 JS 动画包装器,它将接管为您的ng-view. ng-leave当您返回非动画路线时,您需要一个额外的类来处理非动画路线。

这是一个示例 JS 包装器,它检查路由中的自定义animate属性以确定路由是否动画:

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

这是工作的 plunker:
http ://plnkr.co/edit/ldCy9Cfz2lJWNuLzDIbp?p=preview

于 2014-01-10T18:41:32.407 回答
1

据我了解,您想要的是,如果用户点击您的网站,则不会发生动画。但在那之后,动画应该一直发生。这是我知道的最短的解决方案:

使用模块run方法禁用所有动画:

app.run(function($animate){
    $animate.enabled(false);
});

在您的控制器中,它必然会/重新启用动画,但会延迟一个摘要周期:

.controller('rootController', function($timeout, $animate){
    $timeout(function(){
        $animate.enabled(true);
    });
})
于 2014-01-12T15:16:09.917 回答