19

Purpose: I want to add a nice transition effect when click from one page to another


I tried lots of solution online, including:

one thing in common is that they all have style like position: absolute or position: fixed added, which breaks my existing app layout.

I remember when I using Angular 1, there's no need to add position: absolute to <div ui-view><div>

Is it possible in Angular 2 or 4?

Community
  • 1
  • 1
Alex G
  • 1,321
  • 1
  • 24
  • 31
  • Were you able to find a solution for this? – Aamir Khan Mar 27 '17 at 16:29
  • You need position absolute/fixed otherwise when the other screen appear they would be one next to the other. While you need them to cover each other on same coords. In my case rewrote CSS of my web app to allow absolutely positioned routes without breaking the layout. – Martin Nuc Apr 24 '17 at 23:37
  • As of today, I'm also struggling with this. The fact that it seems we must add a `position: fixed` or `position: absolute` seems really dumb and not smart at all to me. I really hope the Angular team is better than that. There has to be another way. My comment is not helping at all, sorry. Will try to find something out and post it here if no one do it before I do. – lkartono Jul 31 '17 at 11:29
  • As @MartinNuc commented, one practical solution for now (4.3.6) seems to be moving from `flex` to `fixed` layout if sliding route animation required. – bob Sep 12 '17 at 23:35
  • @lkartono The `fixed` and `absolute` positioning isn't an Angular thing. If they are `relative`/`static` then they can't overlap - it's a regular HTML thing. The animations have no control over that. There are some options though - you can bind your page `position` styles and update them when the transition starts/ends - this way they are only `absolute` while transitioning, and go back to `relative` when animation ends – Drenai Mar 14 '18 at 19:15
  • @Drenai Even if overlapping is not a required functionality, angular seems to ignore any applied styles during the animation when `absolute` or `fixed` are absent. – realappie Mar 01 '19 at 15:43

2 Answers2

6

You can add the absolute positioning exclusively to the leaving animation.

transition(':enter', [          
    style({transform: 'translateX(100%)'}),    
    animate('0.3s ease-in-out', style({transform: 'translateX(0%)'}))
]),
transition(':leave', [          
    style({transform: 'translateX(0%)', position: 'absolute', left: 0, right: 0, top: 0}),    
    animate('0.3s ease-in-out', style({transform: 'translateX(-100%)'}))
])

So only the leaving route is positioned absolutely, while the entering route is positioned staticly.

If it doesn't work, make sure that your router-outlet is wrapped by position: relative

<div style="position: relative;">
  <router-outlet></router-outlet>
</div>

And that your route-components have display: block

@Component({
  styles:[':host {display: block;}']
Martin Cremer
  • 5,191
  • 2
  • 32
  • 38
3

Talking about Angular version 4.3.x. Reading the router documentation, they explain how to add animation between routes. Here is a resume for the lazy ones (including myself).

You want to import animations libraries from @angular/core (and not @angular/animations):

import {
  AnimationEntryMetadata,
  animate,
  state,
  style,
  trigger
} from '@angular/core';

export const fadeInAnimation: AnimationEntryMetadata = trigger('fadeInAnimation', [
  transition(':enter', [
    style({
      opacity: 0,
      transform: 'translateY(20px)'
    }),
    animate(
      '.3s',
      style({
        opacity: 1,
        transform: 'translateY(0)'
      })
    )
  ])
]);

Then in your component, use the HostBinding decorator in order to specify the component's layout css properties (you don't need use a fixed or absolute position):

import { Component, OnInit, HostBinding } from '@angular/core';

import { fadeInAnimation } from './../animations/fadein';

@Component({
  animations: [fadeInAnimation],
  selector: 'app-posts',
  templateUrl: './posts.component.html'
})
export class DemandsComponent implements OnInit {
  @HostBinding('@fadeInAnimation') fadeInAnimation = true;
  @HostBinding('style.display') display = 'block';
  @HostBinding('style.position') position = 'relative';

  // Rest of the code
}

Adding this to each routed component can be cumbersome. The documentation suggest, and I quote:

Applying route animations to individual components works for a simple demo, but in a real life app, it is better to animate routes based on route paths.

This article from Matias Niemelä can help https://www.yearofmoo.com/2017/06/new-wave-of-animation-features.html#routable-animations

lkartono
  • 2,323
  • 4
  • 29
  • 47