PLNKR - 这里是一个可配置的Angular指令的示例,提供了3D翻转功能的种子。我不认为有任何好的理由使用ngAnimate
。
<flip flip-width="200px" flip-height="100px">
<flip-panel>
content-front
</flip-panel>
<flip-panel>
content-back
</flip-panel>
</flip>
flip-width
和 flip-height
设置了 flip
和两个 flip-panels
的样式。front
和 back
,指令会进行一些基本检查。flip-panel
是 front
,第二个是 back
。transclusion
,flip-panel
的内容可能是任意的 HTML。-webkit
中工作。(更新 使其在 Firefox 中工作,只需将所有带有前缀的部分重复,而不需要前缀 - 不需要 -moz
)PLNKR - 这里是一个更新和扩展版本。它展示了我所说的如何使指令可配置,具体来说:
provider
引入了 flipConfig
,允许在 app.config
中设置:
flip-show
属性,用于指定要显示哪一侧。flip-show
,我们可以从指令外部触发翻转操作。(顺便说一句:它只是一个种子,可以用很多方法改进。例如:指定轴、指定变换原点、指定面板的半径和边距、允许悬停翻转、默认颜色、边距等等)
transclusion: true
不应该在这里。没有它也能正常工作。而将其改为 transclude: true
会破坏事情。 - Misha MoroshkoGithub: https://github.com/zwacky/angular-flippy
P.s.: 看起来我晚了一步 ;)
ng-click
和 ng-class
当翻转容器被点击时添加一个类。<div class="flip-container" ng-click="flip = !flip" ng-class="{'flip': flip}">
<div class="flipper">
<div class="front" style="background: lightblue;">
front
</div>
<div class="back" style="background: lightgreen;">
back
</div>
</div>
</div>
David Walsh的CSS唯一的更改是删除了:hover选择器——HTML结构没有变化。它在Chrome和Firefox中运行得很好,但在IE中翻转效果不太好看。向容器元素添加flip类将使用JavaScript翻转卡片——不需要用户悬停。像document.querySelector("#myCard").classList.toggle("flip")这样的JavaScript注释将会翻转!
app.directive("flipReveal", function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'template.html',
scope: {
url: '=',
flip: '='
}
}
})
免责声明 基于 @artur 的答案 https://dev59.com/537aa4cB1Zd3GeqPt7nS#23139242,但是希望更简化且更灵活。
应该采用自定义指令的方式,可以像这样使用:
<flip flip-side="{{side}}">
<flip-front>
Front side contents
</flip-front>
<flip-back>
Rear contents
</flip-back>
</flip>
我认为它应该具备一定的特性:
Programatically controlled by an attribute. In this case, a string that is equal to 'front' or 'back'
<flip flip-side="{{side}}">....</flip>
this would allow programmatic access via the surrounding scope.
Integrated with ngAnimate
/$animate
. Specifically, if ngAnimate
is removed or disabled, the animation should not occur, but the reveal of the other side happen immediately. Using $animate.addClass
/$animate.removeClass
would achieve this, adding/removing a flip-visible
class together with display:block
and display:none
styles to make sure the right side is visible/hidden when the animations are disabled.
flip > flip-front, flip > flip-back {
display: none;
}
flip > .flip-visible {
display: block;
}
Controlled by CSS, with defaults. So if you want to change the duration of the flip, it's a CSS, and not a Javascript, addition.
So it will have a style sheet to add styles required for the various stages of $animate.addClass
/ $animate.removeClass
CSS animations explained at Year of Moo and $animate docs . The class will be flip-visible
, so the extra classes will be .flip-visible-add
, .flip-visible-add-active
, .flip-visible-remove
, and .flip-visible-remove-active
classes.
The full set of styles can be seen at http://plnkr.co/edit/bbYbMhiURnm6FqC9patp?p=preview, but the main construction is of the form:
.flip-visible-add {
// Initial setup: time and initial, pre-animation, transform
}
.flip-visible-add.flip-visible-add-active {
// Target transform
}
app.directive("flip", function($animate) {
return {
restrict : "E",
controller: function($scope, $element, $attrs) {
var elements = {
'front': $element.find('flip-front'),
'back': $element.find('flip-back')
};
$attrs.$observe('flipSide', function(visibleSide) {
visibleSide = visibleSide || 'front';
var otherSide = visibleSide == 'front' ? 'back' : 'front';
$animate.removeClass(elements[otherSide], 'flip-visible');
$animate.addClass(elements[visibleSide], 'flip-visible');
});
}
}
});
$animate
服务集成,而采用纯基于类的解决方案是有好处的。$animate
与addClass
和removeClass
,但中断动画(例如通过快速重复点击元素),则在Chrome上动画将“抖动”到其结束/起始点,然后从该位置开始动画。使用纯CSS解决此问题,并始终从精确的当前点进行动画,从而产生更平滑的效果。<flip class="{{side === 'front' ? 'flip-front' : 'flip-back'}}">
<flip-front>
Front side contents
</flip-front>
<flip-back>
Rear contents
</flip-back>
</flip>
我使用自定义元素,但它们不需要附加任何指令:它们只是用于CSS的挂钩:
flip > flip-front, flip > flip-back {
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
/* Time can be overriden */
transition: -webkit-transform 0.5s;
transition: transform 0.5s;
}
/* Front visible */
flip > flip-front {
-webkit-transform: perspective(800px) rotateY(0);
transform: perspective(800px) rotateY(0);
}
flip > flip-back {
-webkit-transform: perspective(800px) rotateY(180deg);
transform: perspective(800px) rotateY(180deg);
}
/* Back visible */
flip.flip-back > flip-front {
-webkit-transform: perspective(800px) rotateY(-180deg);
transform: perspective(800px) rotateY(-180deg);
}
flip.flip-back > flip-back {
-webkit-transform: perspective(800px) rotateY(0);
transform: perspective(800px) rotateY(0);
}
您可以在此演示中查看。
<div class="wrapper">
<div class="front"></div>
<div class="back"></div>
</div>
add/remove/setClass()
。该服务通常在指令中使用。您可能希望创建一个指令,以响应单击事件并触发动画。甚至在动画完成时,您还会得到通知。这是对Artur的答案稍作修改后的版本:
angular.module('FlipDemo', []).directive("flip", function() {
return {
restrict : "A",
scope: true,
link: function(scope, element) {
var $panels = element.css({ position: 'relative' }).children().addClass("flip-panel");
var frontPanel = $panels.eq(0);
var backPanel = $panels.eq(1);
scope.showFrontPanel = function() {
frontPanel.removeClass("flip-hide-front-panel");
backPanel.addClass("flip-hide-back-panel");
};
scope.showBackPanel = function() {
backPanel.removeClass("flip-hide-back-panel");
frontPanel.addClass("flip-hide-front-panel");
};
scope.showFrontPanel();
}
}
});
.flip-panel {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-webkit-transition: -webkit-transform .4s;
-moz-transition: -moz-transform .4s;
-webkit-transform: perspective(800px) rotateY(0deg);
-moz-transform: perspective(800px) rotateY(0deg);
}
.flip-hide-back-panel {
-webkit-transform: perspective(800px) rotateY(180deg);
-moz-transform: perspective(800px) rotateY(180deg);
}
.flip-hide-front-panel {
-webkit-transform: perspective(800px) rotateY(-180deg);
-moz-transform: perspective(800px) rotateY(-180deg);
}
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.1/angular.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body ng-app="FlipDemo">
<div style="width: 100px; height: 150px">
<div flip style="width: 100%; height: 100%">
<div style="background-color: green">
<div>Front</div>
<button ng-click="showBackPanel()">Show Back</button>
</div>
<div style="background-color: blue">
<div>Back</div>
<button ng-click="showFrontPanel()">Show Front</button>
</div>
</div>
</div>
<br>
<div style="width: 150px; height: 100px">
<div flip style="width: 100%; height: 100%">
<div style="background-color: green">
<div>Front</div>
<button ng-click="showBackPanel()">Show Back</button>
</div>
<div style="background-color: blue">
<div>Back</div>
<button ng-click="showFrontPanel()">Show Front</button>
</div>
</div>
</div>
</body>
</html>
主要区别: