路线变化的两种不同动画

时间:2013-11-20 18:37:34

标签: angularjs angular-ui-router angularjs-animation

我有以下情况:我在我的AngularJS应用程序中使用ui-router进行路由。在一个路线中,有五种子状态用于不同的子屏幕。我希望以类似旋转木马的方式为它们之间的转换制作动画。

导航如下所示:

Link to A | Link to B | Link to C | Link to D | Link to E

state A导航到state B会使screen A向左滑动,screen B从右侧滑入;反之亦然,可以从state B导航到state A

通过transform: translateX(...);上的enter以及一个方向的leave,屏幕过渡动画效果如何。

通常,我使用带有标记的ng-class控制我的动画。但是,在这种情况下,在ui-view元素上设置类根本不起作用(Angular 1.2和ui-router 0.2还不完全兼容)。也没有使用自定义指令来设置它,该指令监听转换开始后触发的scope.$on "$stateChangeStart"

如何实现所需的行为?

编辑:解决方案

为了记录:我最终使用$scope函数使用$state.go()来实现它,以确定更改路径之前的方向。这可以避免$digest already in progress错误。确定动画的类被添加到ui-view的父元素中;这会以正确的方向为当前和未来ui-view设置动画。

控制器功能(Coffeescript):

go: (entry) ->
  fromIdx = ...
  toIdx = ...

  if fromIdx > toIdx
    $scope.back = false
  else
    $scope.back = true

  $state.go entry

模板:

<div ng-class="{toLeft: back}">
  <div ui-view></div>
</div>

5 个答案:

答案 0 :(得分:26)

您可以通过设置控制器来专门执行此操作来控制视图中的类。然后,您可以订阅应用程序中的事件并更改页面动画的方式。

<div class="viewWrap" ng-controller="viewCtrl">
  <div class="container" ui-view ng-class="{back: back}"></div>
</div>

然后在您的控制器中

.controller('viewCtrl', function ($scope) {
    $scope.$on('$stateChangeSuccess', function (event, toState) {
        if (toState.name === 'state1') {
            $scope.back = true; 
        } else {
            $scope.back = false; 
        }
    });
});

我已经设置了一个codepen来演示http://codepen.io/ed_conolly/pen/aubKf

对于任何想要这样做的人,请注意我必须使用ui.router.compat模块,因为当前Angular 1.2和UI路由器中的动画不兼容。

答案 1 :(得分:3)

您可以随时查看angular-1.2分支:https://github.com/angular-ui/ui-router/tree/angular-1.2。这解决了ngAnimate以及其他一些问题。

我相信这将包含在ui-router 0.3.0中,所以只要你不会很快推出,这应该为你提供你需要的功能,直到你可以回到'稳定'分支

免责声明:我对下一版本的UI路由器何时或将包括什么没有权限。我只是在github页面上的各种问题中找到了这些信息。

答案 2 :(得分:1)

Eddiec的解决方案是一个非常好的开始,但我仍然发现自己有点乱砍。这是一个改进的控制器,更适合我的目的。这更具活力:

function ViewCtrl($scope, $state) {

   $scope.$on('$stateChangeStart', function (event, toState) {
        var movingToParent = $state.includes(toState.name);
        if (movingToParent) {
            $scope.back = true; 
        } else {
            $scope.back = false; 
        }
    });


}

答案 3 :(得分:1)

我尝试使用ngRoute使用$routeChangeSuccess做同样的事情,但我遇到的问题是ng-leave动画会在摘要周期运行之前启动。输入动画始终是正确的,但是假动画始终是前一个。

对我有用的解决方案(Angular 1.57)是将$location.path()调用包装在$timeout中。这样可以确保在动画启动之前运行完整的摘要。

function goto(path) {
    if(nextIndex > currentIndex) {
      ctrl.transition = 'slide-out-left';
    } else {
      ctrl.transition = 'slide-out-right';
    }
    $timeout(function() {
      $location.path(path);
    });
  }

答案 4 :(得分:0)

类似于@ eddiec接受的答案的尝试。基本上是一个状态名称值的数组,然后比较toState和fromState值的数组中的位置,以确定方向。

.controller('viewCtrl', function ($scope) { 
    $scope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) {

        // create an array of state names, in the order they will appear
        var states = ['state1', 'state2', 'state3'];

        if (states.indexOf(toState.name) < states.indexOf(fromState.name)) {
          $scope.back = true; 
        } 
        else {
         $scope.back = false;  
        }
    });
});

Codepen,从上面分叉,显示工作结果。 http://codepen.io/anon/pen/zBQERW