3

我想在 Angular 4 应用程序中为图像交换设置动画。当控制器替换 img src 属性时,旧图像应该消失并出现新图像。

在 AngularJS 中,这可以通过使用 ng-animate-swap 更改不透明度来实现。但是,Angular 4 似乎不支持动画交换。如果没有交换触发器,如何实现这一点?

我尝试为 src 属性添加从 void 到 * 并返回的转换,但这不能按预期工作。第一个图像是动画的,后来交换发生时没有动画。

@Component({
  selector: 'app-play-card',
  template: '<div (click)="loadImg()"><img [@fade]="imgsrc" src="{{ imgsrc }}" /></div>',
  styleUrls: ['./play-card.component.css'],
  animations: [
    trigger('fade', [
      transition('void => *', [
        style({opacity: 0.1}),
        animate(5000, style({opacity: 1}))
      ]),
      transition('* => void', [
        style({opacity: 0.9}),
        animate(5000, style({opacity: 0}))
      ])
    ])
  ]
})
4

3 回答 3

6

以下是我使用 Angular 动画状态的方法:

动画.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(1000)
    ])
  ])
];

app.component.html

<img [@fade]="state" (@fade.done)="onDone($event)" [src]="imageSource" width="500" (click)="onClick()" />

我使用(@fade.done)了 Angular 动画的一个特性,它允许你在动画完成后调用一个方法。

在这里,一旦第一个动画褪色到不透明度为 0,我更改了图像路径,并更改了动画状态,再次褪色并将不透明度值恢复为 1。

app.component.ts

export class AppComponent implements OnInit {
  choice = 2;
  state = 'in';
  counter = 0;
  enableAnimation = false;
  imageSource = '';
  imgSrc1 = 'firstPath';
  imgSrc2 = 'secondPath';

  ngOnInit() {
    this.imageSource = this.imgSrc1;
  }

  onClick() {
    this.enableAnimation = true;
    this.counter = 0;
    this.toggleState();
  }

  toggleImg() {
    if (this.choice === 1) {
      this.imageSource = this.imgSrc1;
      this.choice = 2;
    } else {
      this.imageSource = this.imgSrc2;
      this.choice = 1;
    }
  }

  onDone($event) {
    if (this.enableAnimation) {
      if (this.counter === 1) {
        this.toggleImg();
      }
      this.toggleState();
    }
  }

  toggleState() {
    if (this.counter < 2) {
      this.state = this.state === 'in' ? 'out' : 'in';
      this.counter++;
    }
  }
}

不过,对于一个小动画来说,这显然是很多代码。

这是我为此制作的 StackBlitz 示例:https ://stackblitz.com/edit/angular-anim-fade-img

于 2017-11-28T21:01:30.000 回答
0

我确实尽可能地过滤掉,以免代码过载。我希望代码足够简单,您可以集成它。

gallery.component.ts

import { Component, Input } from '@angular/core';
import { trigger, style, animate, transition } from '@angular/animations';

const animations = trigger('imgAnimation', [
    transition(':enter', [
        style({ opacity: 0 }),
        animate('500ms', style({ opacity: 1 })),
    ]),
    transition(':leave', [
        animate('300ms', style({ opacity: 0 }))
    ])
]);

@Component({
    selector: 'app-gallery',
    templateUrl: './gallery.component.html',
    styleUrls: [],
    animations: [animations]
})
export class GalleryComponent {
    @Input() images: string[];

    index: number = 0;
    imageIndex: number = 0;

    onIncIndex(increment: number = 1) {
        this.index = (this.index + this.images.length + increment) % this.images.length;
        this.imageIndex = null;
    }

    onDone() {
        this.imageIndex = this.index;
    }
}

gallery.component.html

<picture>
    <ng-container *ngFor="let img of images; index as i">
        <img *ngIf="i === imageIndex" 
             @imgAnimation
             (@imgAnimation.done)="onDone()"
             [src]="img">
    </ng-container>
</picture>

<div>
    <button (click)="onIncIndex(-1)">Previous</button>
    <button (click)="onIncIndex()">Next</button>
</div>
于 2021-08-15T12:10:24.923 回答
0

如果您正在使用 2 张图片......你可以做这样的事情......

<mat-icon>
  <img
    [@fadeIn]
    *ngIf="myBool"
    src="assets/svg-icons/back.svg"
    alt=""
  />
  <img
    [@fadeIn]
    *ngIf="!myBool"
    src="assets/svg-icons/close.svg"
    alt=""
  />
</mat-icon>

并且您只想为进入状态设置动画,否则例如两个图像将并排显示

trigger('fadeIn', [
  transition(':enter', [style({ opacity: 0 }), animate(160)]),
  // transition(':leave', [animate(160, style({ opacity: 0 }))]),
]),

您可以解决问题并使图像绝对化,然后您可以为进入和离开状态设置动画(因为这次图像将相互重叠)

于 2022-01-23T10:57:58.080 回答