7

假设我在固定导航栏中有 2 个路由组件和两个 Routerlink 来路由它们。当我单击路由器链接时,我希望它们从右侧滑入。

我不想用 css 抵消组件并使用超时函数来更改 css 类以使其滑入(例如,使用 ngStyle 或 ngClass)。

在 Angular 2 中是否有更优雅的方法可以实现这一点?

谢谢!

4

2 回答 2

15

使用 Angular 4.1,现在可以创建特定的路线动画。这与在显示组件时触发动画不同,因为它可以让您同时为进入/离开组件设置动画以实现平滑过渡,并让您根据即将到来或离开的组件来修改过渡。这意味着您可以进行复杂的转换,例如,如果您正在深入研究内容,则可以从右侧滑入一个组件,如果您通过另一个组件的“后退”按钮输入它,则可以从左侧滑入。

  1. 首先,像这样注释您的路由器插座(例如app.component.html):

    <div class="page" [@routerAnimations]="prepareRouteTransition(outlet)">
        <router-outlet #outlet="outlet"></router-outlet>
    </div>
    
  2. prepareRouteTransition(outlet)在相应的组件定义中实现功能(例如app.component.js)。

    prepareRouteTransition(outlet) {
        const animation = outlet.activatedRouteData['animation'] || {};
        return animation['value'] || null;
    }
    
  3. 定义你的动画(例如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. 将动画元数据添加到您的路线定义中(例如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. 最后,使用您定义的动画和路由元数据在您的组件上注册一个“routerAnimations”动画触发器(例如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),
        ])
      ]
    })
    

不要忘记针对旧浏览器添加 Web Animation API

Matias Niemela 在这里(附有演示)在 ng-conf 上详细讨论了路线动画:https ://youtu.be/Oh9wj-1p2BM?t=12m21s

他的演示代码:https ://github.com/matsko/ng4-animations-preview

于 2017-06-13T23:09:29.557 回答
7

就滑动而言,它非常简单。

您可以参考官方 Angular 2 Animate 文档

您还可以查看我为简单展示所做的Plunker ,使用新的路由器 v3

请记住,当触发的元素即将从视图中销毁时,我正在努力弄清楚如何实际进行离开/退出/无效转换。

我在 Angular 2 Animate 中打开了另一个线程- 更改路由/组件时“* => void”过渡没有可见效果,以试图弄清楚如何让路由器注意到离开动画/过渡时间。

@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)'}))
      ])
    ])
  ]
})
于 2016-06-19T17:12:59.857 回答