0

I would like to be able to flip infinitely an object in one direction or the other by clicking on a button. The animation is inspired by this example: http://www.vishmax.com/en/labs/css-vertical-flip-animation-code-with-demo/

The code: https://codesandbox.io/s/angular-wkbb5?fontsize=14

Here is my template:

<div class="outer">
  <div class="front" [@frontFlipAnim]="flip">
      <img src="http://vishmax.com/demos/images/front.png">
  </div>
  <div class="back" [@backFlipAnim]="flip">
      <img src="http://vishmax.com/demos/images/back.png">
  </div>
</div>

<button (click)="toggleFlip()">Flip</button>

My CSS:

.outer {
  margin-left: 200px;
}
.outer div {
  transition: all .6s;
  position: absolute;
}
.outer div img {
  width: 200px;
}
.front {
  z-index: 999;
}
.back {
  z-index: -999;
  -webkit-transform: rotateX(180deg);
  -moz-transform: rotateX(180deg);
  -o-transform: rotateX(180deg);
  -ms-transform: rotateX(180deg);
  transform: rotateX(180deg);
}

and my component:

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

@Component({
  selector: 'flip',
  templateUrl: './flip.component.html',
  styleUrls: ['./flip.component.scss'],
  animations: [
    trigger('frontFlipAnim', [
      state('up', style({
        transform: 'rotateX(-180deg)',
        zIndex: -999
      })),
      state('down', style({
        transform: 'rotateX(0deg)',
        zIndex: 999
      })),
      transition('up => down', animate('400ms ease-out')),
      transition('down => up', animate('400ms ease-in'))
    ]),
    trigger('backFlipAnim', [
      state('up', style({
        transform: 'rotateX(0deg)',
        zIndex: 999
      })),
      state('down', style({
        transform: 'rotateX(180deg)',
        zIndex: -999
      })),
      transition('up => down', animate('400ms ease-out')),
      transition('down => up', animate('400ms ease-in'))
    ])
  ]
})
export class FlipComponent implements OnInit {

  flip: string;

  constructor() {
    this.flip = 'up';
  }

  ngOnInit() {
  }

  toggleFlip() {
    this.flip = (this.flip === 'up') ? 'down' : 'up';
  }

}

In this example, I can only flip up and down but never flip up infinitely or flip down infinitely like a flip counter.

3
  • you have to loop your animations, because there is no build in "infinite function"
    – jsadev.net
    Commented Nov 8, 2019 at 10:02
  • Does this answer your question? How do I perform infinite animations in Angular 2?
    – jsadev.net
    Commented Nov 8, 2019 at 10:04
  • no because it will do "up => down, down => up, up => down, etc." and I want to be able to do "up => up => up => up, etc." or "down => down => down, etc.". In my code I cannot do this.flipDirection = this.flipDirection, nothing happen. That's my problem.
    – didil
    Commented Nov 8, 2019 at 10:37

1 Answer 1

1

You can try ElementRef, ViewChild, Renderer2 to implement infinite flip on one direction, instead of Angular Animation. You can find the working code below. I hope this is what you are expecting. Please let me know if any issues or your requirement is totally different.

CSS

.outer {
  margin-left: 200px;
  width: 275px;
  height: 475px;
  -webkit-perspective: 900;
}
.outer div {
  width: 275px;
  height: 475px;
  transition: all 0.6s;
  position: absolute;
}
.front {
  z-index: 999;
}
.back {
  z-index: -999;
  -webkit-transform: rotateX(180deg);
  transform: rotateX(180deg);
}

HTML

<button (click)="toggleFlip()">Flip</button>
<div class="outer">
    <div #frontDiv class="front">
        <img src="https://vishmax.com/demos/images/front.png" />
    </div>
    <div class="back" #backDiv>
        <img src="https://vishmax.com/demos/images/back.png" />
    </div>
</div>

Function

toggleFlip() {
    this.transformFront += 180;
    this.transformBack += 180;

    this.renderer.setStyle(
        this.front.nativeElement,
        "-webkit-transform",
        `rotateX(${this.transformFront}deg)`
    );
    this.renderer.setStyle(
        this.back.nativeElement,
        "-webkit-transform",
        `rotateX(${this.transformBack}deg)`
    );
    if (this.flip === "up") {
        this.renderer.setStyle(this.back.nativeElement, "z-index", "999");
        this.renderer.setStyle(this.front.nativeElement, "z-index", "-999");
        this.flip = "down";
    } else {
        this.renderer.setStyle(this.front.nativeElement, "z-index", "999");
        this.renderer.setStyle(this.back.nativeElement, "z-index", "-999");
        this.flip = "up";
    }
}

app.component.ts

import { Component, ElementRef, ViewChild, Renderer2 } from "@angular/core";

@Component({
  selector: "app-root",
  template: `
    <button (click)="toggleFlip()">Flip</button>
    <div class="outer">
      <div #frontDiv class="front">
        <img src="https://vishmax.com/demos/images/front.png" />
      </div>
      <div class="back" #backDiv>
        <img src="https://vishmax.com/demos/images/back.png" />
      </div>
    </div>
  `,
  styles: [
    `
      .outer {
        margin-left: 200px;
        width: 275px;
        height: 475px;
        -webkit-perspective: 900;
      }
      .outer div {
        width: 275px;
        height: 475px;
        transition: all 0.6s;
        position: absolute;
      }
      .front {
        z-index: 999;
      }
      .back {
        z-index: -999;
        -webkit-transform: rotateX(180deg);
        transform: rotateX(180deg);
      }
    `
  ]
})
export class AppComponent {
  flip: string;
  hoverState = false;
  transformFront = 0;
  transformBack = 180;
  @ViewChild("frontDiv") front: ElementRef;

  @ViewChild("backDiv") back: ElementRef;

  constructor(private el: ElementRef, private renderer: Renderer2) {
    this.flip = "up";
  }

  toggleFlip() {
    this.transformFront += 180;
    this.transformBack += 180;

    this.renderer.setStyle(
      this.front.nativeElement,
      "-webkit-transform",
      `rotateX(${this.transformFront}deg)`
    );
    this.renderer.setStyle(
      this.back.nativeElement,
      "-webkit-transform",
      `rotateX(${this.transformBack}deg)`
    );
    if (this.flip === "up") {
      this.renderer.setStyle(this.back.nativeElement, "z-index", "999");
      this.renderer.setStyle(this.front.nativeElement, "z-index", "-999");
      this.flip = "down";
    } else {
      this.renderer.setStyle(this.front.nativeElement, "z-index", "999");
      this.renderer.setStyle(this.back.nativeElement, "z-index", "-999");
      this.flip = "up";
    }
  }
}
2
  • This is really close to what I'm looking for. I'd like to change the #backDiv content at the end of the animation for the next step. Is there a way to trigger a function at the end of the animation? With Angular animations I could use (@itemAnim.done)="animEnd($event)".
    – didil
    Commented Nov 8, 2019 at 11:44
  • codesandbox.io/s/angular-flip-box-97xmc check above link ( LN: 72 ) You can call the function inside toggleFlip() {} function to change #backDiv content. you can use your callback function inside if (this.flip === "up") { } or else part, based on requirement. Commented Nov 8, 2019 at 12:39

Not the answer you're looking for? Browse other questions tagged or ask your own question.