web-dev-qa-db-ja.com

Angular 2アニメーションを使用してフリップ効果を実装するにはどうすればよいですか?

私は自分のプロジェクトで純粋なCSSフリップカードを使用していますが、この解決策は適切ではありません。誰かがボタンをクリックするとangular 2でフリップを提示できますか?angularjsで1つ見つけました https://codepen.io/Zbeyer/pen/oXQrZg

    <div ng-app="cardFlipper" ng-controller="AppController">    
    <h1>Card Flipping AngularJS</h1>
    <div class="flip-container">
        <div class="flipper" ng-click="flipCard()" ng-class="{'flipToFront':isCardRevealed, 'flipToBack':!isCardRevealed}">
            <div class="back" ng-class="{'face-hidden':hideBackFace}">
            </div>
            <div class="front" ng-class="{'face-hidden':!hideBackFace}">
                <h1>{{currentCard.title | uppercase}}</h1>
                <p ng-if="currentCard.icon">{{currentCard.icon}}</p>
                <br ng-if="currentCard.icon" />
                <img ng-if="currentCard.imageUrl" src="{{currentCard.imageUrl}}" alt="currentCard.imageAlt" />
                <p>{{currentCard.description}}</p>
            </div>
        </div>
    </div>

    <footer>
        <div ng-if="currentCard && currentCard.source">
            <a ng-href="{{currentCard.source}}" target="_blank">Source</a>
        </div>
    </footer>
    <br />
    <br />


</div>
<style>
    /* CARD DIMENSIONS */
@width: 19em;
@height: 27em;
@shadow:1em 1em 2em #111111;
/* MIXINS */
.box-shadow (@string:@shadow) {
    -webkit-box-shadow: @string;
    -moz-box-shadow:    @string;
    box-shadow:         @string;
}


.box-sizing(@sizing:border-box) {
    -webkit-box-sizing: @sizing;
    -moz-box-sizing: @sizing;
    box-sizing: @sizing;
}

.border-radius (@radius: 0.5em) {
    -webkit-border-radius: @radius;
    -moz-border-radius: @radius;
    border-radius: @radius;
}

.top-perspective() {
        /*perspective*/
    -webkit-perspective:1000;
       -moz-perspective:1000;
        -ms-perspective:1000;
         -o-perspective:1000;
            perspective:1000;


}

 .flipped-transform-back () {
    /*transform*/
    -webkit-transform:rotateY(180deg);
       -moz-transform:rotateY(180deg);
        -ms-transform:rotateY(180deg);
         -o-transform:rotateY(180deg);
            transform:rotateY(180deg);
}

.flipped-transform-front {
     -webkit-transform: rotateY(0deg);
        -moz-transform: rotateY(0deg);
          -o-transform: rotateY(0deg);
         -ms-transform: rotateY(0deg);
             transform: rotateY(0deg);
}

.flipper-transform(@transition: 0.4s) {
    -webkit-transform-style: preserve-3d;
    -moz-transform-style: preserve-3d;
    -o-transform-style: preserve-3d;
    -ms-transform-style: preserve-3d;
    transform-style: preserve-3d;

    -webkit-transition: @transition;
    -moz-transition: @transition;
    -o-transition: @transition;
    -ms-transition: @transition;
    transition: @transition;
}

.back-face-should-be-hidden() {

    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    backface-visibility: hidden;
}

/* STYLE SHEET */

body {
    font-family: "myriad-pro", sans-serif;
    font-size:100%;
    text-align:center;

    color:#D1D1D1;

    padding: 0;
    background-color:#333333;

    margin:0 auto;
    padding: 0;
}

footer {
    text-align:center;
    padding:1em;
    a {
        font-size:1em;
        color:RGB(255, 208, 128);
    }
}


.flip-container {
    display:block;
    margin:0 auto;
    width: @width * 1.0;
    height: @height *1.0;
}   

.flipToFront {
    .flipped-transform-front();
}

.flipToBack {
    .flipped-transform-back();
}

/* flip speed goes here */
.flipper {
    .top-perspective();
    .flipper-transform();
    width:100%;
    height:100%;
    position:relative;
}

.flip-container, .front, .back {
    .back-face-should-be-hidden();

    text-align:center;
    color:#333333;        
    padding: 0.25em;

    h1, h2, h3, a {
        font-size: 1.25em;
    }
}

.face-hidden {

    /*
        .face-should-be-hidden();
    */
}

.front, .back {
    /* hide back of pane during swap */
    overflow:scroll;

    display:inline-block;

    /* Card overlay eachother */
    position: absolute;
    top: 0;
    left: 0;

    /* Make Pretty */

    .box-sizing();
    .border-radius();    
    .box-shadow();
    width:100%;
    height:100%;
}

/* front pane, placed above back */
.front {
    text-align:center;
    z-index: 2;
    background-color:#FEFEFE;
    .flipped-transform-front ();    
    .box-sizing();
     border:0.5em solid #FEFEFE;
    img {
        width:100%;
        margin: 0 auto;
        height:auto;
        .border-radius();
    }
}

/* back, initially hidden pane */
.back {
    background-color:#EBEBEB;
    .flipped-transform-back ();

    background-image: url('http://subtlepatterns.com/patterns/upfeathers.png');
    background-position: center;
    background-repeat: repeat;
    .box-sizing();
     border:1em solid #FEFEFE;


}

/* Media Queries */

/*
@highdensity: ~"only screen and (-webkit-min-device-pixel-ratio: 1.5)",
              ~"only screen and (min--moz-device-pixel-ratio: 1.5)",
              ~"only screen and (-o-min-device-pixel-ratio: 3/2)",
              ~"only screen and (min-device-pixel-ratio: 1.5)";
*/

@mobile:      ~"only screen and (max-width: 34em)";
@tablet:      ~"only screen and (min-width: 34em) and (max-width: 55em)";
@desktop:     ~"only screen and (min-width: 55em)";


@media @mobile {
    h1, h2, h3 {
        font-size: 1.25em;
    }

    .flip-container, .front, .back {
        width: @width * 1.0;
        height: @height *1.0;
    }
}
/*
@media @tablet {
        .flip-container, .front, .back {
        width: @width * 1.25;
        height: @height *1.25;

        h1, h2, h3 {
            font-size: 1.75em;
        }
    }
}

@media @desktop {
    .flip-container, .front, .back {
        width: @width * 1.5;
        height: @height *1.5;

    }
}*/

<script>
    angular.module('cardFlipper', [])
.controller('AppController', ['$scope', '$interval', function($scope, $interval) {

    $scope.cards = [
    {
        title: "escheresque-dark",
        icon:"",
        imageUrl:"http://subtlepatterns.com/patterns/escheresque_ste.png",
        description:"Sublte Pattern Source image below...",
        source: "http://subtlepatterns.com/escheresque-dark/"
    },
    {
        title: "dark sharp edges",
        icon:"",
        imageUrl:"http://subtlepatterns.com/patterns/footer_lodyas.png",
        description:"Sublte Pattern Source image below...",
        source: "http://subtlepatterns.com/dark-sharp-edges/"
    },
    {
        title: "Grey Washed Wall",
        icon:"",
        imageUrl:"http://subtlepatterns.com/patterns/grey_wash_wall.png",
        description:"Sublte Pattern Source image below...",
        source: "http://subtlepatterns.com/grey-washed-wall/"
    }
];
    $scope.currentCard = {};

    $scope.isCardRevealed = false;
    $scope.flipCard = function() {
        $scope.isCardRevealed = !$scope.isCardRevealed;
        if($scope.isCardRevealed) {
            $scope.generateCard();
        } else {

            $scope.currentCard = {};
            /*            setTimeout(function() {
//                $scope.isBackHidden = !$scope.isCardRevealed;
            }, 0.1 * 1000);
*/            
        }
        /*



        */
    }

    $scope.generateCard = function() {
        $scope.currentCard = {};
        var index = Math.floor((Math.random() * $scope.cards.length) + 0);
         $scope.currentCard = $scope.cards[index];
    }

}]);
</script>

誰かがそれをangular2に変えたり、何か違うものを実装したりできますか?

5
Tomasz Cysewski

angularのアニメーションを使用したこのデモ

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

@Component({
  selector: 'app-root',
  template: `
    <div class="tp-wrapper">
      <div class="tp-box" (click)="toggleFlip()" [@flipState]="flip">
        <div class="tp-box__side tp-box__front">Front
        </div>
        <div class="tp-box__side tp-box__back">Back
        </div>
      </div>
    </div>
  `,
  styles: [
    `
    .tp-wrapper {
      perspective: 800px;
    }

    .tp-box {
      position: relative;
      width: 200px;
      height: 100px;
      margin: 3rem auto;
      transform-style: preserve-3d;
      transition: transform 1s;
    }
    .tp-box__side {
      width: 100%;
      height: 100%;
      position: absolute;
      backface-visibility: hidden;
      color: #fff;
      text-align: center;
      line-height: 100px;
      font-size: 24px;
      font-weight: 700;
      cursor: pointer;
      user-select: none;
    }
    .tp-box__front {
      background: #f30d36;
    }
    .tp-box__back {
      background: #23262d;
      transform: rotateY(179.9deg);
    }

    `
  ],
  animations: [
    trigger('flipState', [
      state('active', style({
        transform: 'rotateY(179.9deg)'
      })),
      state('inactive', style({
        transform: 'rotateY(0)'
      })),
      transition('active => inactive', animate('500ms ease-out')),
      transition('inactive => active', animate('500ms ease-in'))
    ])  
  ]
})
export class AppComponent {

  flip: string = 'inactive';
  constructor() {}

  toggleFlip() {
    this.flip = (this.flip == 'inactive') ? 'active' : 'inactive';
  }

}

オンラインデモ: https://plnkr.co/edit/RZ1v9M?p=preview

16
Tiep Phan

これはChromeでうまく機能しますが、Safari/Firefox/Operaでは、表側が表示されているときに裏返しのコンテンツが(逆に)透けて見えます。その逆も同様ですが、ブラウザ固有の背面表示スタイルを追加する必要があります。

したがって、これを置き換えます。

 backface-visibility: hidden;

これとともに:

-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;

その後、すべてのブラウザで正しく表示されます。

3