我有以下情况:我在我的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>
答案 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