web-dev-qa-db-fra.com

Angular 2 "slide in animation" d'un composant routé

disons que j'ai 2 composants routés et deux Routerlinks dans la barre de navigation fixe pour les router. Je veux qu'ils glissent de la droite lorsque je clique sur les Routerlinks.

Je ne veux pas compenser le composant avec css et utiliser une fonction de temporisation pour changer la classe css pour la laisser glisser (par exemple avec ngStyle ou ngClass).

existe-t-il des moyens plus élégants d'atteindre cela dans Angular 2?

Merci!

7
Han Che

Avec Angular 4.1, il est maintenant possible de créer des animations de route spécifiques. Ceci est différent du déclenchement d'une animation lorsqu'un composant est affiché car cela vous permettra d'animer le composant entrant/sortant en même temps pour une transition fluide et vous permet de modifier la transition en fonction du composant entrant ou sortant. Cela signifie que vous pouvez effectuer des transitions complexes, comme faire glisser un composant de la droite si vous explorez le contenu et le faire glisser de la gauche si vous le saisissez via un bouton "retour" d'un autre composant.

  1. Tout d'abord, annotez votre sortie de routeur comme ceci (par exemple. app.component.html):

    <div class="page" [@routerAnimations]="prepareRouteTransition(outlet)">
        <router-outlet #outlet="outlet"></router-outlet>
    </div>
    
  2. Implémentez la fonction prepareRouteTransition(outlet) dans la définition de composant correspondante (par exemple app.component.js).

    prepareRouteTransition(outlet) {
        const animation = outlet.activatedRouteData['animation'] || {};
        return animation['value'] || null;
    }
    
  3. Définissez vos animations (par exemple app.component.js):

      const slideLeft = [
        query(':leave', style({ position: 'absolute', left: 0, right: 0 ,transform: 'translate3d(0%,0,0)' }), {optional:true}),
        query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(-100%,0,0)' }), {optional:true}),
        group([
          query(':leave', group([
            animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(100%,0,0)' })), // y: '-100%'
          ]), {optional:true}),
          query(':enter', group([
            animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(0%,0,0)' })),
          ]), {optional:true})
        ])
      ]
    
      const slideRight = [
        query(':leave', style({ position: 'absolute', left: 0, right: 0 , transform: 'translate3d(0%,0,0)'}), {optional:true}),
        query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(100%,0,0)'}), {optional:true}),
    
        group([
          query(':leave', group([
            animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(-100%,0,0)' })), // y: '-100%'
          ]), {optional:true}),
          query(':enter', group([
            animate('500ms cubic-bezier(.35,0,.25,1)', style({ transform: 'translate3d(0%,0,0)' })),
          ]), {optional:true})
        ])
      ]
    
  4. Ajoutez les métadonnées d'animation à vos définitions d'itinéraire (par exemple app.routing.ts):

    const routes: Routes = [
      {
        path: 'products',
        component: ProductsComponent,
        data: {
          animation: {
            value: 'products',
          }
        }
      },
      {
        path: 'products/:id',
        component: ProductDetailComponent,
        data: {
           animation: {
            value: 'product-detail',
          }
        }
      }
    
  5. Enfin, enregistrez un déclencheur d'animation 'routerAnimations' sur votre composant avec les animations et les métadonnées de route que vous avez définies (par exemple app.component.js):

    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
      animations: [
        trigger('routerAnimations', [
          transition('products => product-detail', slideRight),
          transition('product-detail => products', slideLeft),
        ])
      ]
    })
    

N'oubliez pas de polyfill l'API Web Animation pour cibler les anciens navigateurs

Matias Niemela parle plus en détail des animations d'itinéraire sur ng-conf ici (avec une démo): https://youtu.be/Oh9wj-1p2BM?t=12m21s

Son code de présentation: https://github.com/matsko/ng4-animations-preview

14
SpaceFozzy

En termes de glissement, c'est assez simple.

Vous pouvez faire référence aux Official Angular 2 Animate docs .

Vous pouvez également vérifier cela Plunker Je l'ai fait pour une simple vitrine, en utilisant le nouveau routeur v3

Gardez à l'esprit que j'ai du mal à comprendre comment avoir réellement les transitions congé/sortie/vide lorsque l'élément déclenché est sur le point d'être détruit de la vue.

J'ai ouvert un autre thread dans Angular 2 Animate - Aucun effet visible de la transition '* => void' lors du changement de routes/composants pour essayer de comprendre comment faire en sorte que le routeur prenne note de l'animation/transition de sortie temps.

@Component({
  selector: 'home',
  directives: [ROUTER_DIRECTIVES],
  template: `
  <div @flyInOut="'active'" class="radibre">
  </div>
  `,
  styles: ['.radibre { width: 200px; height: 100px; background: red; }'],
  animations: [
    trigger('flyInOut', [
      state('in', style({transform: 'translateX(0)'})),
      transition('void => *', [
        style({transform: 'translateX(-100%)'}),
        animate(100)
      ]),
      transition('* => void', [
        animate(100, style({transform: 'translateX(100%)'}))
      ])
    ])
  ]
})

export class Home {
  constructor() { }
}
@Component({
  selector: 'page',
  template: `
  <div @testingBottom="'active'" class="page"></div>`,
  styles: ['.page { width: 300px; height: 50px; background: green; }'],
  animations: [
    trigger('testingBottom', [
      state('active', style({transform: 'scale(1)'})),
      transition('void => *', [
        style({transform: 'scale(0)'}),
        animate(100)
      ]),
      transition('* => void', [
        animate(100, style({transform: 'scale(0)'}))
      ])
    ])
  ]
})
7
Veljko Simakovic