web-dev-qa-db-ja.com

ルート変更のための2つの異なるアニメーション

次のような場合があります。AngularJSアプリケーションのルーティングにui-routerを使用しています。 1つのルートでは、異なる従属画面に5つの子状態があります。これらの間の遷移をカルーセルのようにアニメーション化したいと思います。

ナビゲーションは次のようになります。

_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_に移動する場合はその逆です。

動作するのは、entertransform: translateX(...);oneleaveで画面遷移をアニメーション化することです。方向のみ。

通常、私は_ng-class_とフラグを使用してアニメーションを制御します。ただし、この場合、_ui-view_要素にクラスを設定することはまったく機能しません(Angular1.2とui-router0.2はまだ完全には互換性がありません)。また、遷移の開始後に起動される_scope.$on "$stateChangeStart"_をリッスンするカスタムディレクティブを使用して設定することもできません。

どうすれば目的の動作を実装できますか?

編集:ソリューション

ちなみに、ルートを変更する前に、$state.go()を使用してカスタム_$scope_関数を使用して方向を決定し、実装することになりました。これにより、_$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>
_
21
Sammy S.

特にそれを行うようにコントローラーを設定することにより、ビュー上のクラスを制御できます。その後、アプリ内のイベントをサブスクライブして、ページのアニメーション方法を変更できます。

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

ここでデモンストレーションするためにコードペンを設定しました http://codepen.io/ed_conolly/pen/aubKf

これを行おうとしている人は、Angular 1.2とUIルーターのアニメーションの現在の非互換性のために、ui.router.compatモジュールを使用する必要があることに注意してください。

26
eddiec

いつでもangular-1.2ブランチをチェックアウトできます: https://github.com/angular-ui/ui-router/tree/angular-1.2 。これにより、ngAnimateが他のいくつかの問題とともに修正されます。

これはui-router0.3.0に含まれると思います。すぐにライブをプッシュしない限り、「stable」ブランチに戻るまで必要な機能を提供するはずです。

免責事項:UIルーターの次のリリースがいつになるか、または何が含まれるかについては、私には権限がありません。私はこの情報をgithubページのさまざまな問題で見つけました。

3
Josh

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


}
1
ppalles

_$routeChangeSuccess_を使用してngRouteでこれと同じことを行おうとしましたが、遭遇した問題は、ダイジェストサイクルが実行される前に_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);
    });
  }
_
1
Colin Skow

@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

0