Angular 2 “slide in animation” of a routed component

后端 未结 2 1902
星月不相逢
星月不相逢 2020-12-03 06:30

let\'s say I have 2 routed components and two Routerlinks in the fixed navbar to route them. I want them to slide in from the right when I click the Routerlinks.

I d

相关标签:
2条回答
  • 2020-12-03 06:42

    With Angular 4.1 it is now possible to create specific route animations. This is different from triggering an animation when a component is displayed because it will let you animate the entering/leaving component at the same time for a smooth transition, and let you modify the transition depending on which component is coming or going. That means you can do complex transitions like slide a component in from the right if you're drilling down into content, and slide it in from the left if you're entering it via a 'back' button from another component.

    1. First, annotate your router outlet like so (eg. app.component.html):

      <div class="page" [@routerAnimations]="prepareRouteTransition(outlet)">
          <router-outlet #outlet="outlet"></router-outlet>
      </div>
      
    2. Implement the prepareRouteTransition(outlet) function in the corresponding component definition (e.g. app.component.js).

      prepareRouteTransition(outlet) {
          const animation = outlet.activatedRouteData['animation'] || {};
          return animation['value'] || null;
      }
      
    3. Define your animations (e.g. 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. Add the animation metadata to your route definitions (e.g. 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. Finally, register a 'routerAnimations' animation trigger on your component with the animations and route metadata you defined (e.g. 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),
          ])
        ]
      })
      

    Don't forget to polyfill the Web Animation API to target old browsers

    Matias Niemela talks more about route animations at ng-conf here (with a demo): https://youtu.be/Oh9wj-1p2BM?t=12m21s

    His presentation code: https://github.com/matsko/ng4-animations-preview

    0 讨论(0)
  • 2020-12-03 07:02

    In terms of sliding in it is quite straightforward.

    You can reference to the Official Angular 2 Animate docs.

    You can also check out this Plunker I did for a simple showcase, using the new router v3

    Bear in mind that I am struggling to figure out how to actually have the leave/exit/void transitions when the triggered element is about to be destroyed from the view.

    I opened another thread in Angular 2 Animate - No visible effect of the '* => void' transition when changing routes/components to try to figure out how to make router take notice of the leaving animation/transition time.

    @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)'}))
          ])
        ])
      ]
    })
    
    0 讨论(0)
提交回复
热议问题