3

I lack some understanding, how Angular.io (V8) animation works:

I want to animate a base object and its children:

enter image description here

https://stackblitz.com/edit/angular-yrxvby

<div class="wrap"
    [@anim1]="anim1" [@anim2]="anim2"
    (@anim1.start)="onAnimationEvent($event)"
    (@anim1.done)="onAnimationEvent($event)"
>
    <button [class.active]="anim1" (click)="toggleAnim1()">Anim 1</button>
    <button [class.active]="anim2" (click)="toggleAnim2()">Anim 2</button>

    <hr>
    <b class='b'>B</b>
    <b class='b'>B</b>
    <b class='b'>B</b>
    <b class='b'>B</b>
</div>
import { Component } from '@angular/core';
import { trigger, transition, group, query, style, animate, keyframes, state } from '@angular/animations';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  animations: [
    trigger('anim1', [
      state('true', style({
        border: '10px solid pink',
        backgroundColor: 'purple',
      })),
      state('false', style({
        border: '10px solid lime',
        backgroundColor: 'green',
      })),
      transition('true => false', [
        animate('1s linear')
      ]),
      transition('false => true', [
        animate('.2s linear')
      ]),
    ]),
    trigger('anim2', [
      transition('* => false', [
        query('b', animate( 1000, style({ border: '12px solid cyan' })))
      ]),
      transition('* => true', [
        query('b', animate( 1000, style({ border: '4px solid red' })))
      ]),
    ])
  ] // animations
})
export class AppComponent {
  anim1 = false;
  anim2 = false;

  toggleAnim1() {
    this.anim1 = !this.anim1;
  }

  toggleAnim2() {
    this.anim2 = !this.anim2;
  }

  ngOnInit() {
  }
}

  • animating the base object basically works: purple-ish to green-ish and back (triggered by a status change triggered by a button)
  • animating the contained <b> tags however does not work as expected: Sure, for the time of the transition the color changes (to red-ish resp. blue-ish colors), but before and after it abruptly snaps back to the default color (white border around).

So, it's neithing coming from nor going to its final animation state, so-to-speak. What am I doing wrong?

I did notice, that I put the b-styles within a query within transition (based on stuff I have seen), is there a way, to put them inside a state() ?

Can I combine the main-object animation (anim1) and child animation (anim2)? (In the most simple, toggle-forth-and-back-style way. One variable to forth-and-back 'em all...)

I did notice, that upon reload also the main object sometimes has its (prior-to-animation) css base colors briefly appearing...

If I could I would indeed want to start on everything with the .css-defined colors, thus only have to specify “the other state” (the active one) within the component source, avoiding to replicating the css Styles for “back-to-normal”. Is that possible?

Should I maybe not start with false but with undefined, and/or do something (grouped?) along the lines of * <=> true, false <=> true ?

Frank N
  • 9,625
  • 4
  • 80
  • 110

2 Answers2

0

You cannot achieve it as you thought. There is a limitation between the Parent > child relation. Please see this ticket: https://github.com/angular/angular/issues/18775

The recommended way to achieve this is the following: Add a @child to each element and specify it's end state

<span [@child]="{value:'yes/no', params: { opacity: 0.5 }}"></span>

Pablo
  • 11
  • 1
  • ...but [the documentation](https://angular.io/api/animations/query) „brags“ about being able to animate the children at the same time. - That's the whole point of the `query()`-function, no? [Perhaps there is a misunderstanding about my casual use of the word „state“ in the question: I do not truly want to change any Component's state, I just want to have one „CSS normal definition“ (in the .css/.scss-file), and one „CSS active/heightened definition“ (in the `animation[]`-array), not having to replicate the former. – Frank N Sep 07 '20 at 06:56
  • ...okay, it _is_ the right link. That is indeed a heavy limitation. – Frank N Sep 07 '20 at 11:16
0

First of all, This is a bad practice to implement/handle entire of animations with angular. Keep it simple and let css rules do most of the things. Just do the tricks in Angular in order to reduce lines of code, Although it can implement or handle almost everything. In this way, you create a custom animation (@-webkit-keyframes), css rules for the animation, parent, children, and just control the assignment with angular animation.

To enhance your understanding, just spend a little time on Angular animation which describes basics. For better understanding additional methods:

Now lets discuss about existing problems in you code. the query selector query('b', works but the animation method used incorrectly, As you can see in my fork works for a cubic-bezier.

In case of ordered animations, for example, animating nested elements inside parent, take advantage of animateChild :

Each time an animation is triggered in Angular, the parent animation has priority and any child animations are blocked. In order for a child animation to run, the parent animation must query each of the elements containing child animations, and run them using this function.

Amirhossein Mehrvarzi
  • 18,024
  • 7
  • 45
  • 70