Angular Flip Animation

ε祈祈猫儿з 提交于 2019-12-08 08:09:42

问题


I'm attempting to make a flip animation in Angular. It should flip over the Y-axis when clicked, then flip back over the Y-axis in the reverse direction when clicked again. Additionally, it should have front-side and back-side content that is displayed depending on the flip state.

The back-to-front flip is giving me grief. I'm getting odd behavior depending on what I try. The best I have been able to do is a weird flip which starts in the same direction as the front-to-back flip, then it changes direction at the end. *shrugs*

Note that if you click it before the animation finishes, it works as desired. If you wait for it to finish the animation, then it has the aforementioned behavior.

Here is the prototype: https://angular-epkrtn.stackblitz.io

Can anybody help with the back-to-front flip?


Copying the code from the link below

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

回答1:


I think there are three issues with your code rotateY, scale3d and The background logic. I am no CSS expert and cannot help you a lot with the background logic if its needed to be fixed. It might is another question worth it if crucial for your usecase.

RotateY

  1. Your startpoint (back to front) is 180deg. That initially lets the card flip one way around with 0 time to animate
  2. Your animation direction is the wrong way, you need to animate negative wise.
  3. The provided solution only works if you do not click within the animation. So you need to wait for the @flip.done to be able to click/animate again. Otherwise you start animating from a ~180deg - 0deg rotation and move it around this way

Scale3d You do not finish your animation with the initial value: scale3d(1, 1, 1). I guess that can cause some weird behavior.

Background logic If you start your back to front animation you need to start initially your animation at 0deg. This will cause the front to show up, because your styling is broken there - Therefore I have no solution yet.

Link that fixed the animation: Flip Animation

Full code

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

I hope I could help you. Feel free to ask more or correct me if I am wrong




回答2:


I was able to get the desired behavior with only a minor tweak to the original code. In the back => front transition, the starting value for rotateY is -180deg, not positive 180deg. Everything else is 100% identical.

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

Demo: https://angular-hzuxl9.stackblitz.io



来源:https://stackoverflow.com/questions/55385400/angular-flip-animation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!