9

I have 2 routes :

export const appRoutes: Route[] = [
{
                path: 'page1',
                component: Page1Component,
                data: {
                    animation: 'page1'
                }
            },
{
                path: 'page2',
                component: Page2Component,
                data: {
                    animation: 'page2'
                }
            },
];

My Route animation :

export const routeStateTrigger = trigger('routeState', [
    transition('* => *', [
        query(':enter', [
            style({ position: 'absolute', opacity: 0 })
        ], { optional: true }),
        query(':leave', [
            animate(300, style({ opacity: 0 }))
        ], { optional: true }),
        query(':enter', [
            style({ position: 'relative', opacity: 0 }),
            animate(300, style({ display: 'visible', opacity: 1 }))
        ], { optional: true })
    ])
]);

My router-outlet :

<div [@routeState]="getAnimationData(routerOutlet)">
    <router-outlet #routerOutlet="outlet"></router-outlet>
</div>

and getAnimationData method :

getAnimationData(routerOutlet: RouterOutlet) {
    const routeData = routerOutlet.activatedRouteData['animation'];
    return routeData ? routeData : 'rootPage';
}

This works well, except page transition occurs in two steps (sequential) :

  1. page1 disappears (300 ms)
  2. AND THEN page2 appears (300 ms)

What I want is the disappearing of page1 should happen the same time page2 appears, the transitions should occur simultaneously.

Problem :

I want to prevent the TEMPORARY RESIZING of the content of page1 or page2.

Explanation :

When animating with group() to make them appear-disappear simultaneously AND setting the position temporarily to 'absolute' then the content resizes (because the content is width 100%, and when the container size changes the content changes as well).

I've tried playing with z-index :

position: 'relative', 'z-index': 1

but that didn't work, it's still stacking entering page below leaving page.

Is there a good solution to this ?

Wolf359
  • 2,620
  • 4
  • 42
  • 62

4 Answers4

13

I use CSS only to create fade animation during routing like this:

@keyframes fade {
  0% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

router-outlet + * {
  display: block;  /* Change display inline to block */
  animation: fade 1s;
}

Note: I use global style, you can use more classes to isolate.

Robin Huy
  • 960
  • 7
  • 23
8

I finally made it work :

export const routeStateTrigger = trigger('routeState', [
    transition('* => *', [
        query(':enter', [
                style({ opacity: 0 })
            ], { optional: true }
        ),
        group([
            query(':leave', [
                    animate(300, style({ opacity: 0 }))
                ],
                { optional: true }
            ),
            query(':enter', [
                    style({ opacity: 0 }),
                    animate(300, style({ opacity: 1 }))
                ],
                { optional: true }
            )
        ])
    ])
]);

This CSS selector did the trick :

/deep/ router-outlet~* {
    position: absolute;
    width: 100%;
    height: 100%;
}
Wolf359
  • 2,620
  • 4
  • 42
  • 62
5

Try this simple transition.

export const routeStateTrigger =
  // trigger name for attaching this animation to an element using the [@triggerName] syntax
  trigger('routeState', [

    // route 'enter and leave (<=>)' transition
    transition('*<=>*', [

      // css styles at start of transition
      style({ opacity: 0 }),

      // animation and styles at end of transition
      animate('0.4s', style({ opacity: 1 }))
    ]),
  ]);
  • The entering component appears withing 0.4s gradually, but the leaving component disappears without any animation at all. – Wolf359 Dec 16 '17 at 05:33
  • Check this from yesterday : https://stackoverflow.com/a/47839496/8800147 it's an animation during routing. It uses *:enter* as well, but it uses animation states and *(@animation.done)* when leaving the component to navigate. Hope this helps – br.julien Dec 16 '17 at 15:38
2

Because I was using a footer the positon absolute was not ideal. Here is what i did:

// animation.ts
export const fadeAnimation =

  trigger('fadeAnimation', [

    transition('* => *', [

      query(':enter',
        [
          /* Modified the css here so to push the new element on top while its transitioning */
          style({opacity: 0, position: 'absolute', top: 0, left: 0, width: '100vw', background:'#fff', height: '100vh', 'z-index' : 10})
        ],
        {optional: true}
      ),

      query(':leave',
        [
          style({opacity: 1}),
          animate('0.5s', style({opacity: 0}))
        ],
        {optional: true}
      ),

      query(':enter',
        [
          style({opacity: 0}),
          animate('0.5s', style({opacity: 1}))
        ],
        {optional: true}
      )

    ])

  ]);
// mystyle.scsss
:host {

  main {
    position: relative;
  }

}

Jeffrey Nicholson Carré
  • 2,950
  • 1
  • 26
  • 44