web-dev-qa-db-fra.com

Angular comment retarder / échelonner l'animation à l'intérieur des composants enfants

J'ai un composant enfant avec des animations

child.component.ts

@Component({
  selector: 'child',
  animations:[
    // animations
   ]
})
export class ChildComponent { ... }

Et un composant parent, qui a 2 des composants enfants dans le html

parent.component.hmtl.ts

...
<child></child>
<child></child>
...

Exemple de Stackblitz

Ce que je veux réaliser, c'est échelonner les animations des composants enfants dans le composant parent. Par conséquent, le deuxième composant enfant doit démarrer l'animation après X secondes.

animateChild () semble que cela pourrait fonctionner mais je n'arrive pas à comprendre comment je peux l'utiliser. Est-ce la bonne solution? Si c'est le cas, un exemple serait vraiment utile.

Merci d'avance

[~ # ~] modifier [~ # ~] : animateChild () ne semble pas fonctionner dans ce cas. Apparemment, cela ne fonctionne que sur les animations définies dans le composant parent.

EDIT2 : Je pense qu'il pourrait y avoir une solution de contournement en ajoutant un retard aux animations à l'intérieur des composants enfants.

child.component.ts

@Component({
  selector: 'child',
  animations:[
    animate(x),
    // animations
   ]
})
export class ChildComponent { ... }

Le x serait une variable qui augmenterait pour chaque composant enfant. Cette solution de contournement me semble un peu désordonnée

EDIT3: les réponses jusqu'à présent sont plus ou moins la solution que j'ai mentionnée dans ma deuxième édition. Bien que ceux-ci fonctionnent, je les considère toujours comme des solutions.

Je recherche une solution qui n'implique que le composant parent, donc le composant enfant doit rester tel qu'il est dans cet exemple non fonctionnel

16
Flyii

Selon angular dans la fonction d'animation.

Le deuxième argument, délai, a la même syntaxe que durée. Par exemple:

Attendez 100 ms, puis exécutez 200 ms: "0,2 s 100 ms"

Lecture complète ici

Donc, notre objectif est de passer le deuxième paramètre quelque chose comme ça

animate('2000ms {{delay}}ms'

tout d'abord, ajoutons un paramètre d'entrée à votre composant enfant afin que nous puissions accepter les valeurs d'entrée des parents:

export class ChildComponent implements OnInit {
  @Input() delay: number = 0;
  constructor() { }    
}

Maintenant, passons la valeur du paramètre du composant parent

<p>child1</p>
<app-child [delay]="0"></app-child>

<p>child2</p>
<app-child [delay]="1000"></app-child>
<p>child2 should have a delay</p>

Dans votre composant enfant, nous devons passer ce paramètre au déclencheur d'animation pour qu'il ressemble à ceci

<p [@childAnimation]="{value:'',params:{delay:delay}}">
    IIIIIIIIIIIIIIIIII
</p>

Et enfin, nous pouvons changer notre animation pour prendre en charge cette valeur de paramètre

animations: [
    trigger('childAnimation', [
      transition(':enter', [
        animate('2000ms {{delay}}ms', style({ transform: 'translateX(80%)' })),
        animate('2000ms', style({ transform: 'translateX(0)' })),
      ], { params: { delay: 0 } })
    ])
  ]

tout va bien maintenant, vous devriez travailler retarder les entrées maintenant.

Découvrez la démo ici

7
Just code

Ce ne sont pas les seules options, mais ce sont celles que je connais. Angular 7 compatible.

Démo Stackblitz de travail

Option 1: liaison hôte et états

Dans votre composant enfant, déclarez votre état d'animation en tant que liaison hôte.

@HostBinding('@animationState') animstate : string = 'preanimationstate';

Utilisez ensuite une entrée normale dans votre composant enfant pour obtenir le délai:

@Input('delay') delay : number;

Passez le retard comme ceci:

<child-component [delay]="500"></child-component>

Alors maintenant, dans OnInit, vous pouvez simplement utiliser un délai d'expiration:

let self = this;
window.setTimeout(function () {
    self.animstate = 'newstate';
}, self.delay);

Raisonnement:

Il semble que l'animation d'un enfant puisse également être votre grâce salvatrice, mais cette façon est assez simple et simple. J'espère que ça aide.

Option 2: déplacer l'animation vers HostComponent et appliquer manuellement l'état

Vous pouvez également déplacer votre définition d'animation (si elle utilise des états et des transitions), de child.component.ts vers parent.component.ts , puis démarrez tous vos composants enfants avec un modificateur d'état initial comme celui-ci:

<child [@animstate]="initial"></child>>

Récupérez ensuite vos éléments via ViewChildren :

@ViewChildren(ChildComponent) childComponents as QueryList<ChildComponent>;

Ceci est accessible avec AfterViewInit . Appliquez vos états dans l'initialisation de la vue après en utilisant une boucle for/each et un window.setTimeout Fonction.

3
Terrance00

Juste au cas où quelqu'un trébucherait à nouveau sur ce problème: si vous voulez que les deux animations soient lues en même temps, vous devez simplement utiliser group et animateChild. Fondamentalement, dans le plunker lié dans le premier message, vous devez remplacer outerTransition par ce qui suit:

const outerTransition = transition('void => *', [
  style({opacity: 0}),
  group([
    animate(2000, style({opacity: 1})),
    query('@inner', [
      animateChild()
    ]),
  ]),
]);
0
Ismoil Shifoev