Angular翻转动画

Angular Flip Animation

我正在尝试在 Angular 中制作翻转动画。它应该在单击时翻转 Y 轴,然后在再次单击时以相反方向翻转回 Y 轴。此外,它应该具有根据翻转状态显示的正面和背面内容。

从后到前的翻转让我很伤心。根据我的尝试,我会出现奇怪的行为。我能做的最好的事情是一个奇怪的翻转,它以与从前到后翻转相同的方向开始,然后在最后改变方向。 *耸肩*

请注意,如果您在动画结束前单击它,它会按预期工作。如果你等待它完成动画,那么它就会有上述行为。

这是原型:https://angular-epkrtn.stackblitz.io

有人可以帮忙从后到前翻转吗?


正在复制下面 link 中的代码

app.component.ts

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ],
    animations: [
    trigger('flip', [
      state('front', style({
        transform: 'rotateY(0deg)'
      })),
      state('back', style({
        transform: 'rotateY(180deg)'
      })),
      transition('front => back', [
        animate('1s 0s ease-out',
          keyframes([
            style({
              transform: 'perspective(400px) rotateY(0deg)',
              offset: 0
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(80deg)',
              offset: 0.4
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(100deg)',
              offset: 0.5
            }),
            style({
              transform: 'perspective(400px) scale3d(0.95, 0.95, 0.95) rotateY(180deg)',
              offset: 0.8
            }),
            style({
              transform: 'perspective(400px) rotateY(180deg)',
              offset: 1
            })
          ]))
      ]),
      transition('back => front', [
        animate('1s 0s ease-in',
          keyframes([
            style({
              transform: 'perspective(400px) rotateY(180deg)',
              offset: 0
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(100deg)',
              offset: 0.4
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(80deg)',
              offset: 0.5
            }),
            style({
              transform: 'perspective(400px) scale3d(0.95, 0.95, 0.95) rotateY(0deg)',
              offset: 0.8
            }),
            style({
              transform: 'perspective(400px) rotateY(0deg)',
              offset: 1
            })
          ]))
      ])
    ])
  ]
})
export class AppComponent  {
  flipState = 'front';

  onFlipClick() {
    if (this.flipState == 'front') {
      this.flipState = 'back';
    } else {
      this.flipState = 'front';
    }
  }
}

app.component.html

<div (click)="onFlipClick()" class="flip-card">
    <div [@flip]="flipState" class="flip-card-inner">
        <div class="flip-card-front">
            FRONT
        </div>
        <div class="flip-card-back">
            BACK
        </div>
    </div>
</div>

app.component.css

.flip-card {
    height: 200px; 
    width: 200px; 
    background-color: transparent;
    margin-top: 250px;
    margin-left: auto; 
    margin-right: auto;
}

.flip-card-inner {
    position: relative;
    height: 100%;
    width: 100%;
    transform-style: preserve-3d;
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
}

.flip-card-inner > div {
    position: absolute;
    width: 100%;
    height: 100%;
    backface-visibility: hidden;
}

.flip-card-front {
    background-color: blue;
}

.flip-card-back {
    transform: rotateY(180deg);
    background-color: green;
}

我认为您的代码存在三个问题rotateYscale3d后台逻辑.我不是 CSS 专家,如果需要修复 后台逻辑 ,我无法为您提供很多帮助。如果对您的用例至关重要,这可能是另一个值得提出的问题。

旋转 Y

  1. 你的起点(从后到前)是 180 度。最初让卡片以 0 时间翻转一个方向来制作动画
  2. 你的动画方向错了,你需要做负方向的动画。
  3. 提供的解决方案仅在您不在动画内单击时有效。所以你需要等待@flip.done能够再次click/animate。否则你从 ~180deg - 0deg 旋转开始动画并以这种方式移动它

Scale3d 您没有使用初始值完成动画:scale3d(1, 1, 1)。我想这会导致一些奇怪的行为。

背景逻辑 如果你开始你的backfront动画你需要开始你的动画在 0deg。这将导致前面出现,因为你的样式在那里被破坏了 - 因此我还没有解决方案。

Link 修复了动画Flip Animation

完整代码

trigger('flip', [
      state('front', style({
        transform: 'rotateY(0deg)'
      })),
      state('back', style({
        transform: 'rotateY(180deg)'
      })),
      transition('front => back', [
        animate('1s 0s ease-out',
          keyframes([
            style({
              transform: 'perspective(400px) rotateY(0deg)',
              offset: 0
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(80deg)',
              offset: 0.4
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(100deg)',
              offset: 0.5
            }),
            style({
              transform: 'perspective(400px) scale3d(0.95, 0.95, 0.95) rotateY(180deg)',
              offset: 0.8
            }),
            style({
              transform: 'perspective(400px) scale3d(1, 1, 1) rotateY(180deg)',
              offset: 1
            })
          ]))
      ]),
      transition('back => front', [
        animate('1s 0s ease-in',
          keyframes([
            style({
              transform: 'perspective(400px) rotateY(0deg)',
              offset: 0
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(-80deg)',
              offset: 0.4
            }),
            style({
              transform: 'perspective(400px) scale3d(1.5, 1.5, 1.5) rotateY(-100deg)',
              offset: 0.5
            }),
            style({
              transform: 'perspective(400px) scale3d(0.95, 0.95, 0.95) rotateY(-180deg)',
              offset: 0.8
            }),
            style({
              transform: 'perspective(400px) scale3d(1, 1, 1) rotateY(-180deg)',
              offset: 1
            })
          ]))
      ])
    ])

希望能帮到你。如果我错了,请随时询问或纠正我

我只需对原始代码稍作调整就可以获得所需的行为。在 back => front 过渡中,rotateY 的起始值为 -180deg,而不是正 180deg。其他一切都是 100% 相同的。

  transition('back => front', [
    animate('1s 0s ease-in',
      keyframes([
        style({
          transform: 'perspective(400px) rotateY(-180deg)',
          offset: 0
        }),

演示:https://angular-hzuxl9.stackblitz.io

// card-flip
@Component({
  selector: 'flip-card',
  template: `
    <div class="card-wrapper" (click)="cardFlipped = !cardFlipped" [@cardFlip]="cardFlipped">
      <div class="face front">FRONT</div>
      <div class="face back">BACK</div>
    </div>
  `,
  styles: [
    `
      .card-wrapper {
        transform-style: preserve-3d;
      }

      .face {
        position: absolute;
        height: 100%;
        backface-visibility: hidden;
      }

      .front {
        transform: rotateY(180deg);
      }
    `,
  ],
  animations: [
    trigger('cardFlip', [
      state('false', style({ transform: 'none' })),
      state('true', style({ transform: 'rotateY(180deg)' })),
      transition('false => true', animate('600ms ease-out')),
      transition('true => false', animate('600ms ease-out')),
    ]),
  ],
})
export class FlipCard {
  cardFlipped = false;
}