Uncategorized

Angular Animations API

The Angular Animations API adds a shallow abstraction layer to the animations offered by CSS. It’s a bit like so many other Angular libraries: it adds enough syntactic sugar to make it useful, but it adds little value to the underlying technology.

At least, that was my first impression. During my research for this article, I’ve learned that such a shallow abstraction layer make a lot of sense. For instance, the same API could be used with AngularNative. As far as I know (correct me if I’m wrong!), that’s not the case today, but who knows what the future has in store for us.

Example animation

’nuff said. Let’s get our feet wet with real source code. Have you ever seen at the back-side of your application? This demo doesn’t work with Internet Explorer because I wanted to keep the source code of the demo simple, so please use another browser to see the animation:


Examining the example

The Angular Animation framework has been written to support this kind of animations. In our case, there are two states: either the front-side of the application is shown, or we see the gears on the back-side. The Angular Animations framework adds a smooth transition between these two images.

That’s one of the restrictions: Angular supports any fixed number of states. But these states have to be discrete. You can’t create variable transitions depending on a non-discrete parameter such as, say, the position of the mouse. Plus, these states are defined at compile time.

My original use case was a carousel widget to present images. In other words, it had a dynamic number of states. Angular does not support this. Either you have to find a workaround to emulate a dynamic, initially undetermined number of states, or you have to use a different technology. I’ll come back to the alternatives at the end of this article.

The good news is you can create countless great animations, even within the limitations of the Angular Animations framework. You just have to think out of the box every once in a while.

Numerical values

The second restriction is that each state determines CSS attributes that have to be numerical. You can’t define an animation between an underlined and a regular text, or between two different fonts. That’s because Angular needs to interpolate intermediate values to create a smooth transition between two states.

Luckily, almost every CSS property is numeric, even including colors. So you’ll hardly notice this particular restriction.

Our example consists of two divs occupying the same space, glued together in such a clever way that you only see one of the two divs. The clever bit is making the hidden div visible and hiding the front side after rotating 90°. Read David Walsh’s blog for full details. Suffice it to say that the funny frontside-backside-effect is caused by rotating everything, plus some magic explained by David.

By the way, David Walsh’s blog also shows a working solution for Internet Explorer. Like I’ve said above, I’ve omitted compatibility with IE for the sake of brevity.

Defining an animation

Now you’re equipped to grasp the intent of the source code almost without further explanation. Basically, our animated widget is just that – an Angular component. The interesting part of the animations section of the decorator. One of the first things you’ll recognize is that the animations are triggered by a state.

In our case this state is a variable called showBack. I’ve defined it to be a boolean because there are just two values (showBack=true and showBack). If you need more than two states, you can also use strings, numbers or enums.

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations: [
    trigger('showBack', [
      state('false',
        style({
          transform: 'rotateY(0deg)'
        })),
      state('true', style({
        transform: 'rotateY(180deg)'
      })),
      transition('true <=> false', animate('500ms ease-in-out')),
     ])
  ]
})
export class AppComponent {
  ...
}

The two states both determine the same set of CSS attributes. That’s important because Angular needs to know both the original value and the target value of an attribute in order to calculate a smooth transition.

In our example, it’s exactly one attribute: the rotation. If the state is false, the entire component is rotated by 0 degrees (or not at all). If the state is true, the component is rotated by 180 degrees, bringing the back-side to the top.

There’s also a list of transitions between the states defining how fast the animation is performed. Apart from the time (“500 milliseconds”), you can also define what the animation looks like. “Ease-in” means it starts slowly, “ease-out” means it starts fast and finishes slowly, and “ease-in-out” is a combination of both. There are also several other options. You’ll want to experiment with them. A cleverly selected timing function makes the animation look less sterile. Of course, exaggerating it makes it look playful at best and ridiculous or disturbing at worst.

In our case, the list consists of a single element: true <=> false both covers the transition from true to false and vice versa. It goes without saying you can also define different transition rules for each pair of values.

Angular sugar

Things get interesting when looking at the HTML template of the component. Have a look at the second and the third line:

<div class="flip-container" (click)="showBack = !showBack" >
	<div class="flipper" [@state]="showBack">
		<div class="front">
			<app-front-side></app-front-side>
		</div>
		<div class="back">
			<app-back-side></app-back-side>
		</div>
	</div>
</div>
export class AppComponent {
  public showBack = false;
}

Angular binds the state of the animation to a variable of the component. Switching between the animation states is simply a matter of assigning a new value to the variable, as shown in the second line of the HTML template.

Advanced topics

That’s it in a nutshell. There’s a lot more to discover, but this article deliberately omits the advanced topics. It’s a cursory article, meant to provide you a quick overview of the opportunities and shortcomings of the API. Other bloggers already describe them in much detail. For instance, have a look at Dominic Elm’s deep-dive article. Highly recommended!

Suffice it to simply mention some of the advanced topics. You can call a method when an animation is finished. You can build more complex animations by queuing multiple particle animations. You can trigger an animation by events like “scroll into view”. If you’re using a current Angular version, there’s also limited support for parameters.

Limitations

However, there are also limits to what you can achieve. If I’m not mistaken (correct me if I’m wrong!), there’s no way to use variables of the component class in the animation. In other words, there’s no equivalent to the mustache in the animations section of the component’s decorator. There’s no such thing as {{currentRotation}} in the animations section of the @Component decorator. That’s not surprising because it’s a decorator, but it’s something limiting your flexibility.

I’ve already mentioned the other limitation: you can only use a fixed number of states defined a compile time.

Alternatives

As things go, the use case I’ve used as an excuse to learn about Angular’s animation API requires both features. The number of states is determined at runtime, and I needed variables to define the state transitions. That can’t be done with Angular unless to thing out of the box.

Luckily, Angular adds only a shallow abstraction layer to the CSS animations and transitions. Once you’ve wrapped your head around the Angular animations, it’s not a big deal to learn and use CSS animations (and vice versa). Using CSS directly allows you to calculate the state values programmatically and dynamically, solving the two restrictions I’ve mentioned above.

For instance, I’ve successfully managed to implement a carousel using the Angular Animations API. You can view the source code on my GitHub repository. However, the next version already got rid of Angular in favor of the native CSS animations.

If you need even more options, check out JavaScript-based animation libraries such as GSAP. I didn’t use it yet, but I’m told that GSAP offers you a superior set of options.

Wrapping it up

As of Angular5, the Angular Animations framework provides a small subset of what’s possible with native CSS animations or dedicated libraries such as GSAP. On the other hand, it’s a cleverly selected subset. Chances are it covers every use case you’ll ever encounter. If so, you’re lucky: the syntactic sugar Angular offers is just great. Even if a major part of this articles shows the limitations of the Angular Animations framework, it’s astonishing what you can manage using it. Highly recommended!


Dig deeper

As mentioned above, this article deliberately left out most of the interesting features, so you’re probably interested in one of these articles:
Dominic Elm’s deep-dive article on Angular Animations
What’s new in Angular 4.2?
David Walsh’s blog on turning pages with CSS

Source code of the “application backside” demo

Leave a Reply

Your email address will not be published.