Our website is made possible by displaying online advertisements to our visitors. Please consider supporting us by disabling your ad blocker.

Animate HTML Components In An Angular Application

TwitterFacebookRedditLinkedInHacker News

When building a web application, not only do you need amazing features, but you also need a stunning user experience and that can often be managed by making good use of UI components. When I’m using my favorite web applications, the way components are displayed on the screen are sometimes what makes the application so memorable. Designers will often animate components to make them stand out.

When building a web application you can use CSS keyframe animations, but if you’re using Angular, there is another way. We’re going to see how to use the Angular Animations component to animate UI components on the screen.

There are many ways to animate components, more than what my imagination can think up, so we’re going to keep it simple in what we choose to do. Take the following for example:

Angular Animate Example

In the above animation we are sliding text into a box, pulsing the box, and rotating the text. So what would that look like when it comes to Angular?

Creating a Fresh Angular Project

For simplicity, we’re going to create a new project and expand upon it. We’re going to make the assumption that you have already installed the Angular CLI. From the CLI, execute the following to create a new project:

ng new AnimateProject

Everything we do from here will be done in the default project files. This means we won’t be creating any new files or downloading any further components.

Adding Animation Logic to the TypeScript Code

Before we start developing the actual UI components, let’s figure out how we want to perform our animations. Open the project’s src/app/app.component.ts file and include the following TypeScript code:

import { Component, trigger, state, transition, animate, style, keyframes } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
  animations: [
        trigger("container", [
            state('active', style({ backgroundColor: '#911E25' })),
            transition("inactive => active", [
                animate(1000, keyframes([
                    style({ transform: 'scale(1)' }),
                    style({ transform: 'scale(2)' }),
                    style({ transform: 'scale(1)' }),
                ]))
            ]),
        ]),
        trigger("text", [
            state('inactive', style({ transform: 'translateX(0%)' })),
            state('active', style({ transform: 'rotate(180deg)' })),
            transition(":enter", [
                animate(1000)
            ]),
            transition("inactive => active", [
                animate(1000)
            ]),
        ])
    ]
})
export class AppComponent {

    public currentState: string;

    public constructor() {
        this.currentState = "inactive";
        setTimeout(() => {
            this.currentState = "active";
        }, 2000);
    }

}

There is a lot going on in the above code, so we’re going to break it down.

The first thing we do is import the various animation components that we’ll be using. Within the @Component block we can define those animations.

animations: [
    trigger("container", [
        state('active', style({ backgroundColor: '#911E25' })),
        transition("inactive => active", [
            animate(1000, keyframes([
                style({ transform: 'scale(1)' }),
                style({ transform: 'scale(2)' }),
                style({ transform: 'scale(1)' }),
            ]))
        ]),
    ]),
    trigger("text", [
        state('inactive', style({ transform: 'translateX(0%)' })),
        state('active', style({ transform: 'rotate(180deg)' })),
        transition(":enter", [
            animate(1000)
        ]),
            transition("inactive => active", [
            animate(1000)
        ]),
    ])
]

There are two triggers that we’re defining because we wish to have two different animation sets for two different components. We can use a trigger on as many components as we wish, but the animations will be the same on those components in that scenario.

The container and text trigger names are something random that we’ve defined. We’ve labeled them like this because we want to animate the containing component and the child text component.

When it comes to animation triggers, there are what is known as state and transition definitions. The styles found in a state represent the ending styles. Or in other words what we want the component to look like after the animation completes. The transition is anything that happens between the current state and the final state.

The naming of trigger states can be whatever we want and likewise with transitions, but there are some reserved names for transitions and states that can be read about in the Angular documentation.

trigger("container", [
    state('active', style({ backgroundColor: '#911E25' })),
    transition("inactive => active", [
        animate(1000, keyframes([
            style({ transform: 'scale(1)' }),
            style({ transform: 'scale(2)' }),
            style({ transform: 'scale(1)' }),
        ]))
    ]),
])

For the container animations we want the final component state to be a shade of red. Over the span of 1000ms, the component will grow and shrink back down in a pulse like animation.

trigger("text", [
    state('inactive', style({ transform: 'translateX(0%)' })),
    state('active', style({ transform: 'rotate(180deg)' })),
    transition(":enter", [
        animate(1000)
    ]),
        transition("inactive => active", [
        animate(1000)
    ]),
])

For the text animations, when the component enters, or in other words comes into existence, it goes into the inactive state and translates to the middle of the screen. When the animation state changes, it will rotate 180 degrees.

In the constructor method of our class, we trigger the animation states:

public constructor() {
    this.currentState = "inactive";
    setTimeout(() => {
        this.currentState = "active";
    }, 2000);
}

As soon as the application loads, we change the state to inactive. After a 2000ms timer, the state will activate.

So how do we attach these animations to actual components?

Designing the HTML UI

The corresponding HTML file to our TypeScript will be very simple in comparison. Open the project’s src/app/app.component.html file and include the following HTML markup:

<div [@container]="currentState" style="width: 400px; height: 100px; margin: auto; color: #FFFFFF; background-color: #911E25">
    <p [@text]="currentState" style="position: relative; top: 50%; transform: translateX(-100%) translateY(-50%); text-align: center;">
        Hello World
    </p>
</div>

In the above UI code we have a parent container with a child piece of text. The [@container] and [@text] attributes are linked to the animation triggers. In each component we also define a default set of CSS, some of which will be overridden by the animations.

Conclusion

You just saw how to animate HTML components using the Angular Animations component. These are useful if you want to give your application more flair at minimal price. It is an alternative to using CSS keyframe animations which are also a valid solution. Using Angular you have more control than what you’d find with pure CSS.

Nic Raboy

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in C#, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Unity. Nic writes about his development experiences related to making web and mobile development easier to understand.