Skip to content Skip to sidebar Skip to footer

Angular - Crossfade Between Images

I am trying to create a cross fade effect in Angular but the images keep pulsating instead of fading into each other. How can I fix it? animations.ts import { trigger, style, anima

Solution 1:

There were some changes needed to be performed but basically I changed the value passed to animate() from 500 to 2000 (no worries, with the changes now you can just adjust the transition time you want by changing the value passed to the animate function), also I moved the block of code to change the image to the toggleState function and reorder the strings in the heroImageArray (that was to prevent the error you mentioned about the first image).

Here you have the code https://stackblitz.com/edit/angular-anim-fade-img-yupxe1?file=app%2Fapp.component.ts

Note: to slow or speed the transition, just change the value passed to the animate function.


Solution 2:

when you has an array of pictures you can have an unique imagen and do

fade out--change the image--fade in--fade-out--change the image--fade in-... 

or to have two images (one over the another) and make

fade out --interchange the images --fade out --iterchange the images...

I put the two animations

  animations: [
    trigger("fade", [
      transition("false=>true", [
        style({ opacity: 0 }),
        animate("2500ms", style({ opacity: 1 }))
      ])
    ]),
    trigger("fade2", [
      transition("false=>true", [
        style({ opacity: 0 }),
        animate("2500ms", style({ opacity: 1 }))
      ]),
      transition("true=>false", [animate("2500ms", style({ opacity: 0 }))])
    ])
  ]

(see that "fade" only make a fade out). If you has an array of images - I suggest that, if you make a stackblitz you can use Lorem picsum like instead your server or another one

  imageArray = [
    "https://picsum.photos/200/300?random=1",
    "https://picsum.photos/200/300?random=2",
     ....
  ];

You can has an html like

    <img [@fade2]="toogle2"  
         (@fade2.done)="onFade2($event)"  
         [src]="imageArray[count2%imageArray.length]">

or, if you use two images

    <div style="position:relative">
        <img [@fade]="toogle"  style="position:absolute;z-index:10"
         (@fade.done)="onFade($event)"
         [src]="imageArray[count%imageArray.length]">
        <img [src]="imageArray[(count+imageArray.length-1)%imageArray.length]">
    </div>

The functions onFade and onFade2 use rxjs operator 'timer' to mantain the images visibles during the time you choose

  onFade(event: any) {
    timer(2000).subscribe(() => {
      if (event.fromState)
        this.count = (this.count + 1) % this.imageArray.length;
      this.toogle = !this.toogle;
    });
  }
  onFade2(event: any) {
    if (!event.fromState) {
      timer(2000).subscribe(() => {
        this.toogle2 = !this.toogle2;
      });
    } else {
      this.toogle2 = !this.toogle2;
      if (event.fromState)
        this.count2 = (this.count2 + 1) % this.imageArray.length;
    }
  }

You can see the stackblitz

Updated thanks to the Eliezer Vegas's comment, I could improve the code so "pause" the animation:

  animations: [
    trigger("fade", [
      transition("false=>true", [
        style({ opacity: 0 }),
        animate("2500ms 2000ms", style({ opacity: 1 }))
      ])
    ]),
    trigger("fade2", [
      transition("false=>true", [
        style({ opacity: 0 }),
        animate("2500ms", style({ opacity: 1 }))
      ]),
      transition("true=>false", [animate("2500ms 2000ms", style({ opacity: 0 }))])
    ])
  ]

And

  onFade(event: any) {
      if (event.fromState)
        this.count = (this.count + 1) % this.imageArray.length;
      this.toogle = !this.toogle;
  }
  onFade2(event: any) {
      this.toogle2 = !this.toogle2;
      if (event.fromState)
        this.count2 = (this.count2 + 1) % this.imageArray.length;
  }

Solution 3:

The image should be changed when the state is OUT, otherwise it's gonna flicker. I've forked and updated your stackblitz, the changes are in animations (made the animation 1500ms instead of 500ms), and changed the first picture to the second picture from the array (so it won't flicker to the same picture.

edit: I think it would also be better the change the image on the toggleState event when this.state === AnimationState.OUT (so you know you are switching when the picture is faded out)


Post a Comment for "Angular - Crossfade Between Images"