FLIP

Speaking of FLIP animation, I first came to know it when I talked about transition animation in the official document of VUE. At first, I thought it might be just a front-end animation library, similar to aimate. Js, but in fact, FLIP is just the first letter of the following words

  • First(the initial position of the element)
  • List(position of elements after animation ends)
  • Invert(transform from start to end, see transform)
  • Play(start and stop of animation)

FLIP is just a concept that we might have unconsciously used when we used transitions or animate. I don’t want to talk too much about the concept

animation

Start by creating a container with six cards in it. The wrap is set to flex layout, centered horizontally and vertically, and the six divs wrapped in the wrap are set to absolute position and set to different levels, so that they converge in the center, because six cards first come together and rotate. So we stagger each card by 60 degrees (360/6)

  <div class="wrap">
     <div class="card1 active"></div>
     <div class="card2 active"></div>
     <div class="card3 active"></div>
     <div class="card4 active"></div>
     <div class="card5 active"></div>
     <div class="card6 active"></div>
  </div>
Copy the code
@keyframes xz1 {
    from {
       transform: rotateZ(0deg);
    }
    to {
       transform: rotateZ(360deg); }}.card1 {
        position: absolute;
        z-index: 1;
        animation: xz1 2slinear infinite; }...Copy the code

At this point, the six cards are rotated on top of each other, and then you can use the animate method on the DOM object. You can actually write 👆 code, because you didn’t know there was an animate method in the DOM, so I wanted to try it out

  const arr = document.querySelectorAll('.wrap > div')
  const [dom1, dom2, dom3, dom4, dom5, dom6] = arr
  dom1.animate([
     { transform: 'translateY(0) translateX(0)' },    
     { transform: `translateY(115px) translateX(180)px)`{},],duration: 300.easing: 'cubic - the bezier (,0,0.32 0, 1)',})Copy the code

The first argument in animate refers to @keyFrame in CSS. The second argument is similar to the animate property in CSS (Duration, easeing, direction, delay, fill, Iteration). Element. The animate () portal

Shuffling over, such as six CARDS in sequence into two lines, six CARDS I used here is that the absolute positioning, overlap because the six CARDS need to shuffle, you need to set up level, and reshuffle after returning to his own position, do not set the level div extrusion will happen, I write here because the card number is less so dead, And the order in which six cards fly to six positions is also fixed, because the animation of randomly flying to six positions doesn’t feel very smooth, so if you want a card to randomly fly to one of six positions you can shuffle the order of the array that defines the positions, something like this

const positionArr = [
          positionFunc(115.180),
          positionFunc(115.10),
          positionFunc(115, -160),
          positionFunc(-75.180),
          positionFunc(-75.10),
          positionFunc(-75, -160),
        ].sort(() = > Math.random() - 0.5 )
Copy the code

When you stop shuffling, you simply pause the rotation animation and then switch styles. After switching styles, you just remove animate and add orientation

// Rotate the animation.card1 {
   position: absolute;
   z-index: 1;
   animation: xz1 2slinear infinite; } // After the rotation animation ends.card11 {
   position: absolute;
   z-index: 1;
   left: 0;
   top: 0;
}

Copy the code

Animation also occurs when the center of the shuffle is spread out into six positions, and animate() is used to animate the moving animation

const commonConfig = {
        duration: 300.easing: 'cubic - the bezier (,0,0.32 0, 1)',}const positionArr = [
     positionFunc(-115, -180),
     positionFunc(-115, -10),
     positionFunc(-115.160),
     positionFunc(75, -180),
     positionFunc(75, -10),
     positionFunc(75.160),]const player1 = dom1.animate(positionArr[0], commonConfig)
Copy the code

Finally, in the flip stage, rotateY in transform is used naturally. The idea is to replace the picture of the prize with the picture of the card in the process of rotation, but for the picture of the left and right asymmetry, because the div rotates 180 degrees, the left and right parts will be changed. So either the image itself is upside down, or you can style the IMG tag so that the negatives make the positives

.active > img {
        width: 120px;
        height: 140px;
        transform: rotateY(-180deg);
        object-fit: cover;
      }
Copy the code

Another point to note is that animation is a transitional effect after all. If it is not an infinite loop, the animation will eventually be restored to the original, so we need to keep the last frame in the process of flipping

const player = targetDom.animate(
            [{ transform: 'rotateY(0deg)' }, { transform: 'rotateY(180deg)'}, {duration: 800.easing: 'linear'.fill: 'forwards'.// Save the last frame before the animation ends})Copy the code

As you can see from the above code, it takes 800 milliseconds to turn a card, and the Animation speed is linear, so the best time to replace the card is at 90 degrees in 400 milliseconds. Element.animate() returns an Animation that listens only for cancel and end events. So we’re going to need some other API to listen for its currentTime property all the time

function step(timestamp) {
       if (player.currentTime < 400) {
          requestAnimationFrame(step)
       } else {
          targetDom.innerHTML = `<img src="./img/nodata.png" />`
       }
}

requestAnimationFrame(step)
Copy the code

portal

Finally, the code link is attached for the first time