-1
votes

Angulaire - Fondu enchaîné entre les images

J'essaie de créer un effet de fondu croisé dans Angular mais les images continuent de pulser au lieu de se fondre les unes dans les autres. Comment puis-je y remédier?

animations.ts

export class AppComponent implements OnInit {
  heroImageArray = [
    "https://drscdn.500px.org/photo/277987267/q%3D80_m%3D2000/v2?webp=true&sig=082269b7b07ec17da1847d5c20cffee3a3a91af1f474eb3fd908eba828d5327c",
    "https://drscdn.500px.org/photo/253947845/q%3D80_h%3D450/v2?webp=true&sig=c645b242f19581b17df5bc68d54ee4e5a3c2f5b1ddd41791683ed9c03c455151"
  ];
  heroActiveImage: string =
    "https://drscdn.500px.org/photo/277987267/q%3D80_m%3D2000/v2?webp=true&sig=082269b7b07ec17da1847d5c20cffee3a3a91af1f474eb3fd908eba828d5327c";
  state = AnimationState.IN;

  ngOnInit() {
    this.toggleImg();
  }

  toggleImg() {
    let count = 0;
    setInterval(() => {
      if (count === this.heroImageArray.length) {
        count = 0;
      }
      this.heroActiveImage = this.heroImageArray[count];
      count++;
    }, 3000);
  }

  onDone() {
    this.toggleState();
  }

  toggleState() {
    this.state =
      this.state === AnimationState.IN ? AnimationState.OUT : AnimationState.IN;
  }
}

app.component.ts

import { trigger, style, animate, transition, state } from '@angular/animations';

export const fade = [
  trigger('fade', [
    state('in', style({ 'opacity': '1' })),
    state('out', style({ 'opacity': '0' })),
    transition('* <=> *', [
      animate(500)
    ])
  ])
];

export enum AnimationState {
  IN = 'in',
  OUT = 'out'
}

Stackblitz ici: https://stackblitz.com/edit/angular-anim-fade-img-gga34g


0 commentaires

3 Réponses :


1
votes

L'image doit être modifiée lorsque l'état est OUT, sinon elle va scintiller. J'ai bifurqué et mis à jour votre stackblitz , les changements sont dans les animations (l'animation a été effectuée à 1500 ms au lieu de 500 ms), et j'ai changé la première image en deuxième image du tableau (pour qu'elle ne scintille pas sur la même image.

edit: Je pense qu'il serait également préférable de changer l'image sur l'événement this.state === AnimationState.OUT lorsque this.state === AnimationState.OUT (vous savez donc que vous this.state === AnimationState.OUT lorsque l'image est effacée)


3 commentaires

Cela semble encore un peu bogué lorsque l'image entre dans la première image. Comment puis-je réparer cela?


comme je l'ai dit, vous devriez changer l'image lorsque le fondu est terminé, consultez mon stackblitz mis à jour @methuselah


Merci cela fonctionne très bien, y a-t-il un moyen de ralentir la transition d'animation entre les photos



2
votes

Il y avait quelques changements à effectuer mais en gros, j'ai changé la valeur passée à animate() de 500 à 2000 (pas de soucis, avec les changements maintenant, vous pouvez simplement ajuster le temps de transition que vous voulez en changeant la valeur passée à la fonction d'animation) , j'ai également déplacé le bloc de code pour changer l'image en fonction toggleState et réorganiser les chaînes dans heroImageArray (c'était pour éviter l'erreur que vous avez mentionnée à propos de la première image).

Ici vous avez le code https://stackblitz.com/edit/angular-anim-fade-img-yupxe1?file=app%2Fapp.component.ts

Remarque: pour ralentir ou accélérer la transition, il suffit de changer la valeur passée à la fonction d' animate .


3 commentaires

Merci pour cela, comment régler la durée pendant laquelle l'image reste à l'écran?


Je comprends que vous voulez un délai après l'entrée de l'image. Dans ce cas, vous pouvez passer une chaîne à la fonction d'animation, comme cette animate("2s 1s") (soit 2 secondes de transition et 1 de retard). Vous devez également modifier l'appel de la fonction de transition car le délai s'appliquera pour in => out comme pour out => in créant un délai d'espace vide de 2 secondes. Vous devez avoir 2 appels de transition, la première transition("in => out", animate("2s 2s")) (cela définira le temps que l'image reste à 2 secondes. J'ai mis à jour le code, vous pouvez le vérifier pour info) et une seconde transition("out => in", animate("2s 0.5s")) .


Merci pour ce commentaire, @EliezerVerasVargas, je ne sais pas comment mettre en pause les animations -J'ai utilisé un marteau pour casser des noix, eh bien, vraiment une minuterie rxjs- :)



1
votes

lorsque vous avez un éventail d'images, vous pouvez avoir une image et faire

  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;
  }

ou avoir deux images (l'une sur l'autre) et faire

  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 }))])
    ])
  ]

J'ai mis les deux animations

  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;
    }
  }

(voir que "fondu" ne fait qu'un fondu). Si vous avez un tableau d'images - je suggère que, si vous faites un stackblitz, vous pouvez utiliser Lorem picsum comme à la place votre serveur ou un autre

    <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>

Vous pouvez avoir un html comme

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

ou, si vous utilisez deux images

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

Les fonctions onFade et onFade2 utilisent l'opérateur rxjs 'timer' pour maintenir les images visibles pendant le temps que vous choisissez

  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 }))])
    ])
  ]

Vous pouvez voir le stackblitz

Mis à jour grâce au commentaire d'Eliezer Vegas, j'ai pu améliorer le code afin de "mettre en pause" l'animation:

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

Et

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


0 commentaires