• 12 heures
  • Difficile

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 20/06/2022

Créez des animations complexes

Toutes les animations que vous avez créées dans ce cours sont, pour l'instant, des animations simples. Les éléments sont traités en entier, et tous les éléments avec un même  trigger  sont animés en même temps.

Mais les animations Angular permettent d'aller beaucoup plus loin ! Vous pouvez :

  • animer les éléments enfants indépendamment les uns des autres.

  • étaler les animations des éléments d'une liste dans le temps.

  • gérer des séquences d'animations.

  • générer des animations réutilisables et paramétrables pour améliorer la structure de votre code.

Il est temps de passer les animations de votre application au niveau suivant !

Animez les enfants

Le premier objectif est d'attribuer une animation séparée au texte contenu dans chaque commentaire : vous allez créer un effet fade-in.

Pour ceci, vous allez utiliser la fonction  query  qui permet de cibler des enfants de l'élément qui comporte le  trigger  :

transition(':enter', [
    style({
        transform: 'translateX(-100%)',
        opacity: 0,
        'background-color': 'rgb(201, 157, 242)',
    }),
    animate('250ms ease-out', style({
        transform: 'translateX(0)',
        opacity: 1,
        'background-color': 'white',
    })),
    query('span', [
        style({
            opacity: 0
        }),
        animate('500ms', style({
            opacity: 1
        }))
    ]),
])
  • Vous ciblez les  span  du commentaire et de sa date.

  • Vous leur attribuez un  style  et une  animation  comme ailleurs.

Angular lit ce tableau d'animations dans l'ordre, donc pour avoir le fonctionnement souhaité, on doit faire ceci :

transition(':enter', [
    query('span', [
        style({
            opacity: 0
        }),
    ]),
    style({
        transform: 'translateX(-100%)',
        opacity: 0,
        'background-color': 'rgb(201, 157, 242)',
    }),
    animate('250ms ease-out', style({
        transform: 'translateX(0)',
        opacity: 1,
        'background-color': 'white',
    })),
    query('span', [
        animate('500ms', style({
            opacity: 1
        }))
    ]),
])

Comme ça, le texte est invisible dès le départ, et son fade-in a lieu après l'arrivée du bloc du commentaire.

Gérez une séquence d'animations

Prochain objectif : animer à deux vitesses différentes les deux  span  de chaque commentaire, mais en lançant ces animations en même temps.

Premièrement, il faut pouvoir cibler les deux  span  indépendamment. Je vous propose de leur ajouter des classes CSS :

<span class="comment-text" mat-line>{{ comment.comment }}</span>
<span class="comment-date" mat-line>{{ comment.createdDate | timeAgo }}</span>

Comme ça, le premier  query  pour définir leur opacité à 0 devient :

query('.comment-text, .comment-date', [
    style({
        opacity: 0
    })
]),

Si vous ajoutez ensuite ces animations à la place de l'animation générale des  span  :

query('.comment-text', [
    animate('250ms', style({
        opacity: 1
    }))
]),
query('.comment-date', [
    animate('500ms', style({
        opacity: 1
    }))
]),

Les textes sont animés, mais puisque Angular lit les animations de haut en bas, ces animations sont déclenchées l'une à la suite de l'autre.

Pour les déclencher ensemble, Angular vous propose la fonction  group  :

group([
    query('.comment-text', [
        animate('250ms', style({
            opacity: 1
        }))
    ]),
    query('.comment-date', [
        animate('500ms', style({
            opacity: 1
        }))
    ]),
])

Quand ces animations sont déclenchées en même temps, le ressenti global est plus organique (je trouve !).

Mettez des séquences dans des groupes

Par défaut, les animations Angular sont lues en série, sauf quand on utilise  group  pour les lire en parallèle.

Mais qu'est-ce qui se passe lorsque l'on veut déclencher une séquence d'animations en même temps que d'autres animations ?

Par exemple, si vous voulez faire "flasher" la couleur de fond du commentaire (l'animer vers une couleur puis tout de suite animer son retour au blanc), et déclencher ce flash en même temps que les fade-in des textes  ?

Pour ce type d'animation, vous allez ajouter la  sequence  qui correspond au flash au  group  des fade-in comme suit :

group([
    sequence([
        animate('250ms', style({
            'background-color': 'rgb(255,7,147)'
        })),
        animate('250ms', style({
            'background-color': 'white'
        })),
    ]),
    query('.comment-text', [
        animate('250ms', style({
            opacity: 1
        }))
    ]),
    query('.comment-date', [
        animate('500ms', style({
            opacity: 1
        }))
    ]),
]),

Cette animation précise n'est pas très belle, soit ! Mais elle vous montre comment gérer le parallélisme de vos animations avec  group  et  sequence  .

Étalez les animations

Actuellement, tous les commentaires sont animés en même temps. Un effet dynamique sympa pourrait être de les faire apparaître en décalé, c'est-à-dire déclencher les animations à des écarts de X millisecondes les unes après les autres.

Avec seulement le trigger  listItem  , ce genre de comportement n'est pas possible. Du coup, vous allez créer un nouveau trigger qui viendra se placer sur le parent  mat-list  :

trigger('list', []),
<mat-list *ngIf="comments.length" @list>

Ce qui vous intéresse, c'est l'arrivée dans le DOM de cet élément, donc vous allez utiliser une transition "depuis le vide", et il faudra cibler les enfants  mat-list-item  à animer.

Vous pourriez utiliser leur sélecteur HTML, mais je vous propose une autre approche :

trigger('list', [
    transition(':enter', [
        query('@listItem', [
          
        ])
    ])
]),

Ici, vous ciblez tous les enfants dotés du trigger  listItem  , donc c'est parfait !

Pour déclencher les animations d'un élément enfant, vous allez utiliser  animateChild  , et pour décaler ces déclenchements dans le temps, vous allez utiliser  stagger  :

trigger('list', [
    transition(':enter', [
        query('@listItem', [
            stagger(50, [
                animateChild()
            ])
        ])
    ])
]),

La valeur  50  correspond au nombre de millisecondes entre deux déclenchements !

Rendez vos animations réutilisables

Pour créer une animation réutilisable, vous allez utiliser la méthode  animation  .

Dans  shared  , créez un dossier  animations  . La première animation que vous allez déporter correspond au "flash", donc créez un fichier  flash.animation.ts  :

import { animate, animation, sequence, style } from '@angular/animations';

export const flashAnimation = animation([
  sequence([
    animate('250ms', style({
      'background-color': 'rgb(201, 157, 242)'
    })),
    animate('250ms', style({
      'background-color': 'white'
    })),
  ]),
])

Vous pouvez maintenant remplacer cette  sequence  dans CommentsComponent par :

useAnimation(flashAnimation)

et vous aurez exactement le même comportement.

Faites de même avec ces lignes :

style({
    transform: 'translateX(-100%)',
    opacity: 0,
    'background-color': 'rgb(201, 157, 242)',
}),
animate('250ms ease-out', style({
    transform: 'translateX(0)',
    opacity: 1,
    'background-color': 'white',
})),

en créant  slide-and-fade.animation.ts  :

import { animate, animation, style } from '@angular/animations';

export const slideAndFadeAnimation = animation([
    style({
        transform: 'translateX(-100%)',
        opacity: 0,
        'background-color': 'rgb(201, 157, 242)',
    }),
    animate('250ms ease-out', style({
        transform: 'translateX(0)',
        opacity: 1,
        'background-color': 'white',
    })),
]);

Vous pouvez donc les remplacer dans CommentsComponent par :

useAnimation(slideAndFadeAnimation)

Ces animations sont maintenant réutilisables, mais on peut mieux faire : on peut les rendre paramétrables

Pour créer un paramètre dans une animation, on utilise la string interpolation, mais à l'intérieur des strings :

import { animate, animation, sequence, style } from '@angular/animations';

export const flashAnimation = animation([
  sequence([
    animate('{{ time }}', style({
      'background-color': '{{ flashColor }}'
    })),
    animate('{{ time }}', style({
      'background-color': 'white'
    })),
  ]),
])

Cette syntaxe fait que  flashAnimation  accepte deux paramètres :  time  et  flashColor  .

Pour passer des arguments à ces paramètres depuis les components, vous ajoutez un objet de configuration à  useAnimation  :

useAnimation(flashAnimation, {
    params: {
        time: '250ms',
        flashColor: 'rgb(249,179,111)'
    }
}),

Vous pouvez faire de même pour  slideAndFadeAnimation  :

import { animate, animation, style } from '@angular/animations';

export const slideAndFadeAnimation = animation([
  style({
    transform: 'translateX(-100%)',
    opacity: 0,
    'background-color': '{{ startColor }}',
  }),
  animate('{{ time }} ease-out', style({
    transform: 'translateX(0)',
    opacity: 1,
    'background-color': 'white',
  })),
]);

Et dans le component :

useAnimation(slideAndFadeAnimation, {
    params: {
        time: '5004ms',
        startColor: 'rgb(201, 157, 242)'
    }
}),

Ainsi, vous avez créé deux animations réutilisables et paramétrables, deux mots que nous aimons tous entendre lorsqu'il s'agit de nos outils de développement !

En résumé

  • Utilisez  query  pour cibler les différents enfants de l'élément animé.

  • Déclenchez des animations en parallèle avec  group  , ou en série avec  sequence .

  • Étalez des animations de liste avec  stagger .

  • Déclenchez l'animation d'un élément enfant avec  animateChild .

  • Rendez vos animations réutilisables avec  animation , et utilisez-les avec  useAnimation .

  • Ajoutez des paramètres à vos animations avec la string interpolation, et passez des arguments pour ces paramètres via un objet de configuration passé à  useAnimation .

Pour terminer cette deuxième partie, faites le quiz suivant. Après, on se retrouve dans la prochaine partie pour parler des formulaires !

Exemple de certificat de réussite
Exemple de certificat de réussite