web-dev-qa-db-ja.com

Angular 2.0ルーターおよびコンポーネントインターフェイスの約束を伴うページ遷移アニメーション

Angular 1.xでは、ngAnimateを使用して、特定のルートを出入りするタイミングを検出できます。さらに、それらにビヘイビアを適用できます。

animateApp.animation('.myElement', function(){

    return {

        enter : function(element, done) {
            //Do something on enter
        },

        leave : function(element, done) {
            //Do something on leave
        }
    };

)};

次のような製品になります: http://embed.plnkr.co/uW4v9T/preview

私はAngular 2.0で似たようなことをしたいと思います。

そこで、メインアプリケーションコンポーネントにhomeaboutコンポーネント間のナビゲーションを制御するシンプルなルーターを作成しました。 。

import { bootstrap, bind, Component, provide, View } from 'angular2/angular2';
import {RouteConfig, RouteParams, ROUTER_DIRECTIVES, ROUTER_PROVIDERS, APP_BASE_HREF, ROUTER_BINDINGS} from 'angular2/router'




/////////////////////////////////////////////////////////////////
// Home Component Start
/////////////////////////////////////////////////////////////////
@Component({
  selector: 'home-cmp'
})

@View({
  template: `
    <h2 class="title">Home Page</h2>
  `
})

class HomeCmp implements OnActivate, onDeactivate{

  onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
    console.log("Home Page - initialized");
  }

  onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
    console.log("Home Page - destroyed");
  }

}
/////////////////////////////////////////////////////////////////
// Home Component End
/////////////////////////////////////////////////////////////////




/////////////////////////////////////////////////////////////////
// About Component Start
/////////////////////////////////////////////////////////////////
@Component({
  selector: 'about-cmp'
})

@View({
  template: `
    <h2 class="title">About Page</h2>
  `
})

class AboutCmp implements OnActivate, onDeactivate {

  onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
    console.log("About Page - initialized");
  }

  onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
    console.log("About Page - destroyed");
  }

}
/////////////////////////////////////////////////////////////////
// About Component End
/////////////////////////////////////////////////////////////////




/////////////////////////////////////////////////////////////////
// Main Application Componenent Start
/////////////////////////////////////////////////////////////////
@Component({
  selector: 'my-app'
})

@View({
  template: `
    <div>
      <h1>Hello {{message}}!</h1>
      <a [router-link]="['./HomeCmp']">home</a>
      <a [router-link]="['./AboutCmp']">about</a>
      <hr>
      <router-outlet></router-outlet>
    </div>
  `,
  directives: [ROUTER_DIRECTIVES]
})

@RouteConfig([
  {path: '/', component: HomeCmp, as: 'HomeCmp'},
  {path: '/about', component: AboutCmp, as: 'AboutCmp'}
])

export class App {
}
/////////////////////////////////////////////////////////////////
// Main Application Componenent End
/////////////////////////////////////////////////////////////////




bootstrap(App, [
  ROUTER_BINDINGS,
  ROUTER_PROVIDERS,
  ROUTER_DIRECTIVES,
  provide(APP_BASE_HREF, {useValue: '/'})
])

現在、特定のコンポーネントが次から次へ移動するときに、ルーターが特定のコンポーネントをインスタンス化または破壊したことをキャプチャできます。これは素晴らしいですが、previousコンポーネントがdestroyedの場合、を適用することはできません次のコンポーネントが初期化される前のleave遷移アニメーション。

class HomeCmp implements OnActivate, onDeactivate{

    onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
        //This works
        TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1});
    }

    onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
        //This get ignored
        TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1});
    }

}

約束を使用してこれに対する解決策があるようです。彼らが述べているAngular.ioのAPIプレビュー:

onDeactivateがプロミスを返す場合、ルートの変更はプロミスが安定するまで待機します。

そして

onActivateがpromiseを返す場合、ルート変更は、promiseが落ち着いて子コンポーネントをインスタンス化およびアクティブ化するまで待機します。

https://angular.io/docs/ts/latest/api/

私は約束に非常に新しいので、これをコードにまとめて、次のコンポーネントの初期化で現在のコンポーネントが破壊される問題を解決しましたが、その後、neverは破壊されます、その新しいインスタンスのみを作成します。そこに戻るたびに、新しいインスタンスが作成され、複数のコピーが作成されます。

onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {

    function ani(){
      TweenMax.fromTo($(".title"), 1, {opacity: 1}, {opacity: 0});
    }

    var aniPromise = ani();

    aniPromise.then(function (ani) {
        ani();
    });

}

要約すると、ルーターは、現在のコンポーネントがbusinessを完了するのを待ってから、それを破棄して次のコンポーネントを初期化できる必要があります。

私はすべてが理にかなっていることを望み、私は本当に助けに感謝します!

25
SimonHawesome

あなたがドキュメントから引用したように、このフックのいずれかがPromiseを返す場合、次のものに移動するために完了するまで待機するので、基本的に何もせずに1秒(またはあなたと同じくらいの時間)簡単にPromiseを返すことができます必要)。

 onActivate(next: ComponentInstruction, prev: ComponentInstruction) {
    TweenMax.fromTo($(".title"), 1, {opacity: 0}, {opacity: 1});
    return new Promise((res, rej) => setTimeout(() => res(1), 1000));
  }

  onDeactivate(next: ComponentInstruction, prev: ComponentInstruction) {
    TweenMax.fromTo($(".title"), 1, {opacity:1}, {opacity: 0});
    return new Promise((res, rej) => setTimeout(() => res(1), 1000));
  }

SetTimeoutを実行するPromiseを返すことに注意してください。アニメーションが完了するのに十分な時間を与えるために1秒待機します。

私はsetTimeoutsの使用があまり好きではないので、Observablesも使用できます。

return Rx.Observable.of(true).delay(1000).toPromise();

ここでは、ランダムな値(この場合はtrue)を渡し、1秒遅延させて、最終的にPromiseにキャストしています。はい、最終的にPromiseになりますが、直接使用しません。

これが plnkr の例で、動作しています(探しているものを期待しています)。

PS:Rxへのパスが見つからないと不平を言う場合は、機能するまで更新し続けるだけです(Rx.jsを手動で追加しましたが、plnkrにはちょっと重いです)。

13
Eric Martinez

Angular 2最終ソリューション:

plunk

簡単に言うと、@routeAnimationこれを実現する組み込みディレクティブ。子ルートを表す各コンポーネントは、次のようなもので装飾されます。

@Component({
  selector: 'app-pageone'
  Host: { '[@routeAnimation]': 'true' },
  styles: [':Host { width: 300px; display: block; position: absolute; }']
  animations: [
    trigger('routeAnimation', [
      state('*', style({transform: 'translateX(0)', opacity: 1})),
      transition('void => *', [
        style({transform: 'translateX(-100%)', opacity: 0}),
        animate('0.5s cubic-bezier(0.215, 0.610, 0.355, 1.000)')
      ]),
      transition('* => void',
        animate('0.5s cubic-bezier(0.215, 0.610, 0.355, 1.000)', style({
          transform: 'translateX(100%)',
          opacity: 0
        }))
      )
    ])
  ]
})
9
Stephen Paul