Untitled

mail@pastecode.io avatar
unknown
plain_text
a year ago
3.5 kB
5
Indexable
Never
HTML:

<div class="container">
    <form class="toggle">
        <input type="radio" id="choice1" [(ngModel)]="choice" name="choice" value="speed">
        <label for="choice1">Speed</label>

        <input type="radio" id="choice2" [(ngModel)]="choice" name="choice" value="quality">
        <label for="choice2">Quality</label>

        <div id="flap" [@rotateFlap]="choice"><span class="content">{{ flapContent }}</span></div>
    </form>
</div>

app.component.ts:
import { Component } from '@angular/core';
import { trigger, state, style, transition, animate } from '@angular/animations';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  animations: [
    trigger('rotateFlap', [
      state('speed', style({
        transform: 'rotateY(-180deg)'
      })),
      state('quality', style({
        transform: 'rotateY(0deg)'
      })),
      transition('speed <=> quality', animate('0.5s cubic-bezier(0.4, 0, 0.2, 1)'))
    ])
  ]
})
export class AppComponent {
  choice = 'quality';
  flapContent = 'quality';

  constructor() {
    setTimeout(() => {
      this.updateFlapContent();
    });
  }

  updateFlapContent() {
    this.flapContent = this.choice;
  }
}

app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    BrowserAnimationsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }


app.component.scss:
$accent: #04da97;
$border-width: 6px;
$border-radius: 55px;
$font-size: 30px;

body {
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    margin: 0;
    background-color: #333;
    font-family: sans-serif;
}

.container {
    perspective: 800px;
}

.toggle {
    position: relative;
    border: solid $border-width $accent;
    border-radius: $border-radius;
    transition: transform cubic-bezier(0, 0, 0.30, 2) .4s;
    transform-style: preserve-3d;
    perspective: 800px;
}

.toggle > input[type="radio"] {
    display: none;
}

.toggle > #choice1:checked ~ #flap {
    transform: rotateY(-180deg);
}

.toggle > #choice1:checked ~ #flap > .content {
    transform: rotateY(-180deg);
}

.toggle > #choice2:checked ~ #flap {
    transform: rotateY(0deg);
}

.toggle > label {
    display: inline-block;
    min-width: 170px;
    padding: 30px;
    font-size: $font-size;
    text-align: center;
    color: $accent;
    cursor: pointer;
}

.toggle > label,
.toggle > #flap {
    font-weight: bold;
    text-transform: capitalize;
}

.toggle > #flap {
    position: absolute;
    top: calc(0px - $border-width);
    left: 50%;
    height: calc(100% + $border-width * 2);
    width: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: $font-size;
    background-color: $accent;
    border-top-right-radius: $border-radius;
    border-bottom-right-radius: $border-radius;
    transform-style: preserve-3d;
    transform-origin: left;
    transition: transform cubic-bezier(0.4, 0, 0.2, 1) .5s;
}

.toggle > #flap > .content {
    color: #333;
    transition: transform 0s linear .25s;
    transform-style: preserve-3d;
}