How to implement a flip over effect using AngularJ

2019-03-09 05:45发布

What would be the best way to achieve a flip over effect using AngularJS animations?

I would like the flip over effect to occur on click. Every time it's clicked, it should flip over to the other side.

Ideally, I guess, I'm looking for a directive implementation that uses Angular animations.

8条回答
We Are One
2楼-- · 2019-03-09 06:00

I realise there is a benefit to not integrating with the $animate service, and having a purely class-based solution.

If you use $animate with addClass and removeClass, but interrupt the animation (say, by clicking quickly and repeatedly on the element), the animation will 'jerk' to its end/starting point, and then animate from that position, at least on Chrome. Using a pure CSS solutions avoids this issue, and always animates from the exact current point, giving a smoother effect.

An added benefit is the solution is also simpler, and you don't need a custom directive.

For example, the HTML can be as follows:

<flip class="{{side === 'front' ? 'flip-front' : 'flip-back'}}">
  <flip-front>
    Front side contents
  </flip-front>
  <flip-back>
    Rear contents
  </flip-back>
</flip>

I use custom elements, but they don't need to have any directives attached: they are just for CSS to hook into:

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);   
}

This can be seen in a demo at http://plnkr.co/edit/A7IeGa1JEsZishmTDTaK?p=preview

查看更多
Bombasti
3楼-- · 2019-03-09 06:01

You can use ng-click and ng-class to add a class when the flip container is clicked.

<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>

This is essentially the angular way of doing what Walsh suggested in his article:

Adding the flip class to the container element will flip the card using JavaScript -- no user hover required. A JavaScript comment like document.querySelector("#myCard").classList.toggle("flip") will do the flip!

The only change to David Walsh's css was removing the :hover selector - the html structure is unchanged. It works nicely in chrome and firefox.. but the flip isn't as pretty in IE.

Here is a working demo: http://plnkr.co/edit/0dn775vpuoOeh2PS1T6k?p=preview

Update
I created a simple directive to encapsulate this basic technique. It allows you to flip over a black card, to reveal a picture on the other side.

app.directive("flipReveal", function() {
  return {
    restrict: 'E',
    replace: true,
    templateUrl: 'template.html',
    scope: {
      url: '=',
      flip: '='
    }
  }
})

Here is a link to a new demo: http://plnkr.co/X4pSav

demo

查看更多
爱情/是我丢掉的垃圾
4楼-- · 2019-03-09 06:01

You are going to want to create 3 divs.

<div class="wrapper">
    <div class="front"></div>
    <div class="back"></div>
</div>

You then position back behind front using z-index, and flip it upside down using rotateX (-180deg or so). Set a transition on wrapper as well.

Then, on click of wrapper, rotateX(+180deg). This will pretty much infinitely flip it over.

** Update: For angular, bind to click and use setClass to toggle between two classes on wrapper, one at rotateX(0deg) , the other at rotateX(180deg)

查看更多
老娘就宠你
5楼-- · 2019-03-09 06:07

Here is a slightly modified version of artur's answer:

DEMO

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>

Main differences:

  • Works in Chrome and Firefox.
  • More flexibility with when the flip happens.
  • Just one directive rather than two. Less code.
  • I took the CSS outside of the directive for clarity sake.
查看更多
孤傲高冷的网名
6楼-- · 2019-03-09 06:13

PLNKR - here is a seed of a configurable angular directive that provides 3d flipping functionality. I do not see any good reason why to use ngAnimate for it.

basic usage

<flip flip-width="200px" flip-height="100px">
   <flip-panel>
     content-front
   </flip-panel>
   <flip-panel>
     content-back
   </flip-panel>
</flip>

Comments

  1. It appends css-styles on its own, to be fully independent.
  2. In a proper, generic directive all names should be configurable.
  3. flip-width and flip-height sets style of flip and both flip-panels.
  4. Directive makes some basic check, if both front and back are set.
  5. First flip-panel is front and the second is back.
  6. Due to usage of transclusion content of the flip-panel may be arbitrary html. (you are right Misha no transclusion needed)
  7. It only works in -webkit. (update to make it work in Firefox, just duplicate all pieces with -webkit with no prefix - you do not need -moz)

UPDATE

PLNKR - here is an updated and extended version. It shows what I meant by making the directive configurable. In more details:

  1. Introduced flipConfig via provider, that allows to set in app.config:
    • default dimensions
    • css class names
    • speed of the transition
    • if the flip action is triggered by a click on the panel
  2. Introduced flip-show attribute that specifies which side to show.
  3. Changing flip-show we can trigger the flip action from outside of the directive.
  4. It works in Firefox and [almost:-)] in IE11.

(btw: it is just a seed and it may be improved in a lot of ways. E.g: specifying axis, specifying origin of the transform, specifying radius and margin of the panels, allowing flip on hover, defaults colors, margins and so on)

查看更多
疯言疯语
7楼-- · 2019-03-09 06:13

I had the same usecase just recently for an angular memory game.

My implementation is the same by the idea of the other answers. I also released the flipping code along with a DEMO.

Github: https://github.com/zwacky/angular-flippy

P.s.: Looks i'm late to the party ;)

查看更多
登录 后发表回答