如何使用 Angular 2 动画实现翻转效果?
How to implement a flip effect using Anuglar 2 animations?
我一直在我的项目中使用纯 css 翻牌,但这个解决方案并不合适。有人可以通过单击按钮显示 angular 2 中的翻转吗?我在 angularjs 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 或实现不同的东西吗?
此演示使用 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';
}
}
这在 Chrome 中效果很好,但在 Safari/Firefox/Opera 中,当正面可见时,翻转的内容显示(反向),反之亦然,但您只需要添加浏览器特定的背面可见性样式。
所以替换这个:
backface-visibility: hidden;
有了这个:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
然后它会在所有浏览器中正确显示。
我一直在我的项目中使用纯 css 翻牌,但这个解决方案并不合适。有人可以通过单击按钮显示 angular 2 中的翻转吗?我在 angularjs 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 或实现不同的东西吗?
此演示使用 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';
}
}
这在 Chrome 中效果很好,但在 Safari/Firefox/Opera 中,当正面可见时,翻转的内容显示(反向),反之亦然,但您只需要添加浏览器特定的背面可见性样式。
所以替换这个:
backface-visibility: hidden;
有了这个:
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
然后它会在所有浏览器中正确显示。