Angular 4 路由动画

8

我正在开发的应用程序需要具备通过路由前进和后退的能力,因此当您以一定方向通过应用程序导航时,组件会从左到右进行动画,而当您返回时,它们将从右到左进行导航。

即:

component1 -> component2 =  left -> right animation
component2 -> component1 = right -> left animation

我可以在NG4中轻松实现这一点,但问题是它不能同时导航退出和进入组件。退出组件只会消失,进入组件则会动画显示。

我也可以在NG2中实现这个目标 - 但当你有条件动画时就会变得复杂。例如:

component2 -> component3 = left -> right animation
component2 -> component1 = right -> left animation

问题在于根据下一个或上一个路由触发不同的动画。
有人有解决方案吗?无论是NG2还是4,解决同时在任何方向上都动画化两个视图的问题?
我没有把这个放在plunkr上,因为我不知道如何在那里设置一个NG4应用程序。抱歉。
我的NG4解决方案基于this demo apphttps://github.com/matsko/ng4-animations-preview,但基本上在我的app.component.ts中,我有以下动画:
animations: [
    trigger('routerAnimations',[
        transition('page1 => page2',[
            style({transform: 'translateX(100%)'}),
            animate('500ms')
        ]),
        transition('page2 => page1', [
            style({transform: 'translateX(-100%)'}),
            animate('500ms')
        ]),
        transition('page2 => page3',[
            style({transform: 'translateX(100%)'}),
            animate('500ms')
        ]),
        transition('page3 => page2',[
            style({transform: 'translateX(-100%)'}),
            animate('500ms')
        ]),
        transition('page3 => page4',[
            style({transform: 'translateX(100%)'}),
            animate('500ms')
        ]),
        transition('page4 => page3',[
            style({transform: 'translateX(-100%)'}),
            animate('500ms')
        ])
    ])
]

还需要一个函数,从每个路由中获取动画值并将其绑定到app.component.html中的<router-outlet>变量上:

export class AppComponent {
    prepareRouteTransition(outlet) {
        let routeData: any;
        try {
            routeData = outlet['_activatedRoute'].snapshot.routeConfig['animation'];
       } catch(e) {
           return '';
       }
       return routeData.value;
    }
}

上面的函数获取动画值,该值用于动画中定义过渡的起始和结束值:

export const APP_ROUTES = [{
    path: '',
    component: Page1Component,
    animation: {
      value: 'page1',
    }
  }, 
  {
    path: 'page2',
    component: Page2Component,
    animation: {
      value: 'page2',
    }
  },
  {
    path: 'page3',
    component: Page3Component,
    animation: {
        value: 'page3'
    }
  },
  {
      path: 'page4',
      component: Page4Component,
      animation: {
          value: 'page4'
      }
  }
];

app.component.html:

<div class="page" [@routerAnimations]="prepareRouteTransition(outlet)">
  <router-outlet #outlet="outlet"></router-outlet>
</div>

这里也有同样的问题,我遇到了同样的障碍。你解决了吗? - elecash
谢谢@Clay,我已经测试过了,它运行得非常好 :) 然而,我会等待4.1.0,因为实现更加清晰,但是现在这应该是被接受的答案。 - elecash
2个回答

8
现在,您可以通过定义查询:enter:leave元素的动画来实现此目的。以下示例将平滑地动画退出路由并动画进入路由:
const slideLeft = [
  query(':leave', style({ position: 'absolute', left: 0, right: 0 ,transform: 'translate3d(0%,0,0)' })),
  query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(-100%,0,0)' })),
  group([
    query(':leave',
      animate('1s', style({ transform: 'translate3d(100%,0,0)' }))),
    query(':enter',
      animate('1s', style({ transform: 'translate3d(0%,0,0)' })))
  ])
]

const slideRight = [
  query(':leave', style({ position: 'absolute', left: 0, right: 0 , transform: 'translate3d(0%,0,0)'})),
  query(':enter', style({ position: 'absolute', left: 0, right: 0, transform: 'translate3d(100%,0,0)'})),

  group([
    query(':leave',
      animate('1s', style({ transform: 'translate3d(-100%,0,0)' }))),
    query(':enter', 
      animate('1s', style({ transform: 'translate3d(0%,0,0)' })))
  ])
]

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

0

您可以通过将动画放置在要进行动画处理的路由出口周围而不是视图本身来实现此目的。

此外,您需要在一个组([])中执行动画,这将使两个动画同时运行。

<!-- app.html -->
<div [@routeAnimation]="prepRouteState(routerOutlet)">
 <!-- make sure to keep the ="outlet" part -->
 <router-outlet #routerOutlet="outlet"></div>

 class AppComponent {
 prepRouteState(outlet: any) {
     return outlet.activatedRouteData['animation'] || 'firstPage'; 
   } 
 }

<!-- app.ts -->
const ROUTES = [
   { path: '',
     component: HomePageComponent,
     data: {
       animation: 'homePage'
     }
   },
   { path: 'support',
     component: SupportPageComponent,
     data: {
       animation: 'supportPage'
     }
   }
 ]

// the animation itself
trigger('routeAnimation', [
  //...
  transition('homePage => supportPage', [
    group([
      query(':enter', [
        style({ opacity: 0 }),
        animate('0.5s', style({ opacity: 1 })),
        animateChild()
      ]),
      query(':leave', [
        animate('0.5s', style({ opacity: 0 })),
        animateChild()
      ])
    ])
  ]),
  //...
])

如同在YearofMoo Routable Animations中所见


函数prepRouterState,不要返回出口,你可以在程序级别上做任何你想做的事情并返回你的动画状态。从那里,你可以根据你返回的内容进行动画处理,例如从3到1向左或从1到3向右或从3到2向左等等。你必须构建一个函数,给你想要的正确状态,然后动画将从那里开始工作。 - Zuriel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接