Angular 4 component responsive animations

neoswf picture neoswf · Sep 13, 2017 · Viewed 8.1k times · Source

I am working on an Angular responsive app, which on mobile it has a drawer.

I love Web Animations API implementation in Angular, but I can't find a place where I can configure animations based on my media-queries breakpoints.

All I can find is canceling the animations via my css sheet, but thats make me start to spread the code on different places in my project, and I'm not sure that this is what angular intended for me to do...

Real life example

My application drawer uses this code to animate

<div class="mobile-menu" [@animateDrawer]="drawerOpened">
  <!-- Drawer's menu goes here -->
</div>

drawerOpened is a boolean that toggle when app menu button is pressed.

My component looks like that:

@Component({
  selector: 'app-header',
  templateUrl: './header.component.html',
  styleUrls: ['./header.component.scss'],
  animations: [
    trigger('animateDrawer', [
      state('inactive', style({
        transform: 'translate3d(-100%, 0, 0)'
      })),
      state('active', style({
        transform: 'translate3d(0, 0, 0)'
      }))
    ])
  ]
})

The CSS code where I cancel the animations effects

.mobile-menu {
  opacity: 1 !important;
  display: flex !important;
  transform: none !important;
}

Besides manipulating all in my css code & disabling the css properties on Desktop BreakPoint, does exist some way to do it inside Angular context?

Thank you!

Answer

Aaron Martin-Colby picture Aaron Martin-Colby · Sep 18, 2017

There is no way to define JavaScript behavior based on CSS @Media queries. You will have to do what I did, where I created an Angular appearance service that monitors viewport dimensions and sends commands to components based on what is detected. You can then control animations and appearance with JavaScript logic instead of CSS logic.

Adding an example:

Create a service that monitors viewport width. If the viewport is less than, say, 500px, the service outputs "mobile," else, it outputs "desktop."

In your component, declare one trigger, we'll call it @slide, with multiple states. We will also set a private variable called stateOfYourChoosing, and you can set it to a string.

Then, in your template

<div [@slide]="stateOfYourChoosing"></div>

You can then choose which state you want the default state of stateOfYourChoosing to be, and how you want your component to transition based on component logic.

So, if your appearance service outputs "desktop," your default stateOfYourChoosing would be "slideOut."

transition('slideOut => slideIn', animate('100ms ease-in'))

If the appearance service outputs "mobile," it sets stateOfYourChoosing to "mobileSlideOut," and your transition code is instead

transition('mobileSlideOut => mobileSlideIn', animate('100ms ease-in'))

You can then control all of your responsive animations in your animations module by controlling in what state your trigger is.