Developer Programs

Learn

Docs

Animation

Components > Miscellaneous > Animation
Use this feature to...
Add subtle motion to elements in your application

Overview

Applications can create an emotional connection with the user when they respond in a natural way. One way to achieve this is through the use of transitional animations. These animations help the user better understand how their interactions control the app, help the app feel more alive, and provide a sense of polish and quality that enhances the user experience and the user’s overall perception of the app.

In order to be effective, these animations must be:

  • Subtle: Animations must support the user experience but never get in the way. We don’t want to draw attention to the animations; we want to reinforce real-world motion metaphors for these elements.
  • Fast: The user must never be forced to wait for an animation to complete before being able to interact with the element.
  • Optional: The user must be able to turn off animations for accessibility reasons.

Component-Level Animations

Most of the animations in your app are already built into Responsive UI, so you get these for free. You can see most of these in this very site. These include the following:

  • The nav bar animates when it expands and collapses.
  • Nav dropdown buttons animate when they expand and collapse.
  • Mega menus, header dropdowns, and the Bootstrap dropdown animate when they expand.
  • Color changes animate when you hover over header and nav buttons.
  • In each function, the title slides up while the content fades in, providing a smooth visual transition between views.

Application-Level Animations

You can also add optional animations at the application level for elements within your views. These can be especially useful for displaying templated lists, where each item in the list fades and slides in.

Be careful to not overuse this mechanism and animate too many elements in a view, or you can risk fatiguing the user’s eye.

Development

Most of the animations in your app are already built into Responsive UI, so you get these for free. You can see these animations in this site.

You can also add optional animations at the application level for elements within your views. This can be a pleasing effect for displaying templated lists, although you can also animate elements that are part of the DOM just as easily. You can animate one or more sets of HTML elements in the view.

Each animated element starts out transparent, then quickly fades into view and scales in from the top-left of the list, one at a time.

There is a short delay between each element’s animation, so if you animate a very large number of elements, the overall impact may be quite noticeable to the user and may delay their ability to see and interact with elements further down the list. You should experiment with animation on a case-by-case basis and see if it’s a good fit for each view.

Responsive UI turns off component animations for users that have a vestibular disorder (which can be triggered by animations or parallax) by honoring the prefers-reduced-motion CSS media feature. This feature taps into OS-level settings that specify the user’s motion preferences.

Allowing the user to disable animations in your application is an important consideration for accessibility.

Web component development

Animating elements in your view consists of the following steps:

  • In the HTML, pick a string that you’ll use as an ID prefix for every related element that you want to animate as a set, then specify the ID for each of these elements as a combination of that prefix followed by a zero-based next-in-line number.
    • For example, if the elements you want to animate as a set represent a list of accounts, you might set the IDs for these elements as “account0”, “account1”, “account2”, etc.
    • If you’re using *ngFor to iterate over a list of objects in Angular, it can be helpful to add let i=index to the *ngFor statement. This way “i” refers to the zero-based index of the item in the list, which you can concatenate after the ID prefix to get the proper ID for each element.
  • In the HTML, add the rui-animated-list-item-initial CSS class to each of the elements you want to animate.
    • This sets the initial display settings required for the animation to work properly. Note that this CSS class sets the element’s opacity to 0, so even though the element is present in the DOM, it will be transparent until the animation brings it into view.
    • This CSS class sets display:block on the element. If this breaks the behavior needed in the element, you can either override that setting with another CSS class or an inline style, or you can wrap the element with a new div and animate the new containing div instead.
  • In the Typescript, import the ruiAnimateElements function from @jkhy/responsive-ui-wc/js/rui-animation.
  • In the Typescript, call the ruiAnimateElements function, passing in a reference to the component’s element, the ID prefix you selected above, and the number of elements that you want to animate as a set.
    • You should call this method at the proper time in the code. For fixed elements in your HTML, that can be in the ngOnInit method. For templated lists, that should be after you populate the array of objects that back the templated list.
      • For fixed elements in your HTML, that can be in the ngOnInit method.
      • For templated lists, that should be after you populate the array of objects that back the templated list.
    • This method iterates from 0 to the element count, looking for each element in the DOM that matches the ID prefix concatenated with the current element index. It then applies a CSS class that animates the element’s opacity and scale in order to fade it in while scaling from the top-left of the list.

In the example below, we’re using tiles to display a templated lists of accounts. We add let i=index to the *ngFor to get the zero-based index for each item in the list, then we append that to our arbitrarily selected “account” ID prefix to construct the ID for each item in the list (which will be “account0”, “account1”, etc). We then set the rui-animated-list-item-initial CSS class on each element to provide the proper initial display settings before the animation runs. (For HTML elements that are fixed in your view and not generated by *ngFor, just manually assign the IDs using the same prefix + zero-based index format.)

Animating tiles: HTML
<rui-tile *ngFor="let account of listItems;let i=index" id="account{{i}}" class="rui-animated-list-item-initial"
    titleText="{{account.name}}" iconType="{{account.iconType}}" size="wide">
    {{account.subheader}}<br />
    {{account.balance | jhaCurrency}}
</rui-tile>

In the TypeScript we import the ruiAnimateElements function from @jkhy/responsive-ui-wc/js/rui-animation. We then call that function after populating the account list, passing in our “account” ID prefix and the length of the account list as parameters.

Animating tiles: Typescript
import { Component, OnInit, ElementRef } from '@angular/core';
import { ruiAnimateElements } from '@jkhy/responsive-ui-wc/js/rui-animation';

@Component({
    selector: 'animation',
    templateUrl: './animation.component.html',
    styleUrls: ['./animation.component.scss']
})
export class AnimationComponent implements OnInit {
    public listItems = [
        { iconType: 'check', name: 'Primary Checking', subheader: 'John Smith', balance: 1248.19 },
        { iconType: 'savings', name: 'Basic Savings', subheader: 'John Smith', balance: 3144.72 },
        { iconType: 'time-deposit', name: '24 Month CD', subheader: 'John Smith', balance: 2500.0 },
        { iconType: 'auto', name: 'Auto Loan', subheader: 'John Smith', balance: 18219.23 },
        { iconType: 'home', name: 'Home Mortgage', subheader: 'John Smith', balance: 472936.50 },
        { iconType: 'check', name: 'Family Checking', subheader: 'Timmy Smith', balance: 422.16 },
        { iconType: 'check', name: 'Family Checking', subheader: 'Brenda Smith', balance: 723.88 }
    ];

    constructor(private elRef:ElementRef) { }

    ngOnInit(): void {
        ruiAnimateElements(this.elRef.nativeElement, 'account', this.listItems.length);
    }
}

Angular wrapper development

Application-level animations can be developed in two different ways:

  • For content that is static or loaded without delay you can use the jhaAnimation directive.
  • For content that needs to be fetched before loading the content blocks, you can call the jhaAnimationService once the content is loaded and ready to be presented.

Animating Static Data

Animating static data elements in your view consists of the following steps:

  • In the HTML, add the jhaAnimation directive to the parent container of the content you want to animate.
  • Add the jhaAnimationCount attribute to the same parent container to tell the animation service how many elements will be included in the animation.
  • The content elements that are to be animated will need an id that consist of a combination of a prefix followed by a zero-based next-in-line number. By default, the jhaAnimation directive will look for elements using the prefix “animate” (i.e. “animate0”, “animate1”, “animate2”). You can select a custom prefix by using the jhaAnimationPrefix attribute and setting your prefix accordingly.

Begin by importing JhaResponsiveCoreModule into your application.

Import the module
// import into app.module
import { JhaResponsiveCoreModule } from '@jkhy/responsive-ui-angular/jha-responsive-core';

@NgModule({
    imports: [
        ...
        JhaResponsiveCoreModule.forRoot(),
        ...
    ]
})

export class AppModule(){}

In the example below, we’re using tiles to display a templated lists of accounts. We add the jhaAnimation directive to the parent container of the content we want to animate. Next we add the jhaAnimationCount attribute and enter the number of elements to animate. Finally, we want to customize the id for these elements, so we add the jhaAnimationPrefix attribute and set the value to “account”.

Animating static data
<div jhaAnimation jhaAnimationCount="4" jhaAnimationPrefix="account">

    <jha-tile id="account0" jhaTitle="Primary Checking" jhaIconType="Check">
        John Smith<br />
        {{1248.19 | jhaCurrency}}
    </jha-tile>

    <jha-tile id="account1" jhaTitle="Basic Savings" jhaIconType="Savings">
        John Smith<br />
        {{3144.72 | jhaCurrency}}
    </jha-tile>

    <jha-tile id="account2" jhaTitle="24 Month CD" jhaIconType="TimeDeposit">
        John Smith<br />
        {{2500.0 | jhaCurrency}}
    </jha-tile>

    <jha-tile id="account3" jhaTitle="Auto Loan" jhaIconType="Loan">
        John Smith<br />
        {{18219.23 | jhaCurrency}}
    </jha-tile>

</div>

Animating Dynamic Data

Animating dynamic data elements in your view consists of the following steps:

  • In the HTML, pick a string that you’ll use as an ID prefix for every related element that you want to animate as a set, then specify the ID for each of these elements as a combination of that prefix followed by a zero-based next-in-line number.
    • For example, if the elements you want to animate as a set represent a list of accounts, you might set the IDs for these elements as “account0”, “account1”, “account2”, etc.
    • If you’re using *ngFor to iterate over a list of objects, it can be helpful to add let i=index to the *ngFor statement. This way “i” refers to the zero-based index of the item in the list, which you can concatenate after the ID prefix to get the proper ID for each element.
  • In the HTML, add the jha-animated-list-item-initial CSS class to each of the elements you want to animate.
    • This sets the initial display settings required for the animation to work properly. Note that this CSS class sets the element’s opacity to 0, so even though the element is present in the DOM, it will be transparent until the animation brings it into view.
    • This CSS class sets display:block on the element. If this breaks the behavior needed in the element, you can either override that setting with another CSS class or an inline style, or you can wrap the element with a new div and animate the new containing div instead.
  • In the Typescript, import JhaAnimationService from the jha-responsive-core module. Next, inject it in the component’s constructor.
  • In the Typescript, call the animation service’s AnimateElements method, passing in the ID prefix you selected above and the number of elements that you want to animate as a set.
    • You should call this method at the proper time in the code. For fixed elements in your HTML, that can be in the ngOnInit method. For templated lists, that should be after you populate the array of objects that back the templated list.
      • For fixed elements in your HTML, that can be in the ngOnInit method.
      • For templated lists, that should be after you populate the array of objects that back the templated list.
    • This method iterates from 0 to the element count, looking for each element in the DOM that matches the ID prefix concatenated with the current element index. It then applies a CSS class that animates the element’s opacity and scale in order to fade it in while scaling from the top-left of the list.

In the example below, we’re using tiles to display a templated lists of accounts. We add let i=index to the *ngFor to get the zero-based index for each item in the list, then we append that to our arbitrarily selected “account” ID prefix to construct the ID for each item in the list (which will be “account0”, “account1”, etc). We then set the jha-animated-list-item-initial CSS class on each element to provide the proper initial display settings before the animation runs. (For HTML elements that are fixed in your view and not generated by *ngFor, just manually assign the IDs using the same prefix + zero-based index format.)

Animating dynamic data: HTML
<jha-tile *ngFor="let account of accounts;let i=index" id="account{{i}}" class="jha-animated-list-item-initial"
    jhaTitle="{{account.Name}}" jhaIconType="{{account.IconType}}" jhaSize="Wide">
   {{account.Subheader}}<br />
   {{account.Balance | jhaCurrency}}
</jha-tile>

In the TypeScript we import the JhaAnimationService from the jha-responsive-core module, and inject it into our constructor. We then call the animation service’s AnimateElements method after populating the account list, passing in our “account” ID prefix and the length of the account list as parameters.

Animating dynamic data: TypeScript
import { Component, OnInit } from '@angular/core';
import { JhaAnimationService } from '@jkhy/responsive-ui-angular/jha-responsive-core';
import { ListItem } from './listItem';

@Component({
    selector: 'animation',
    templateUrl: './animation.component.html',
    styleUrls: ['./animation.component.css']
})
export class AnimationComponent implements OnInit {
    public accounts: ListItem[] = [];

    constructor(private jhaAnimationService: JhaAnimationService) { }

    ngOnInit(): void {
        this.getList().then((Data) => {
            this.accounts = Data;
            this.jhaAnimationService.AnimateElements('account', this.accounts.length);
        });
    }
}

Design

There are no design elements specific to animation. Animation works with the other existing elements in your designs.


Support options
Have questions on this topic?
Join the Responsive UI team in Microsoft Teams to connect with the community.
See something in this page that needs to change?
Send us feedback on this page.
Last updated Mon May 1 2023