background

Ps: This development is based on wePY framework

Because recently received a demand – raffle activities;

Flip cards disrupt activities raffle activities, probably the demand is like this, nine palace card, first front display of all prizes, and then the card flip, shuffled sorting, click cards, and then the lottery.

This requirement itself is not difficult, mainly divided into three steps;

  • Show all the cards and flip them over.
  • Shuffle all cards
  • Click on one of the cards to draw

Step 1: Flip the card

We first render nine cards in the DOM.

<view class="card-module">
  <view class="card {{showClass ? 'change' : ''}}> front card-item">{{cardItem.front}} back card-item">{{cardItem.back}}   Copy the code

Generate mock card data in data

cardData: [
    {
      animationData: {},
      front: '1' positive,
      back: Reverse '1'},... . { animationData: {}, front:'positive 9',
      back: 'tails 9'
    }
  ],
  showClass: false.Copy the code

Render the basic style of the card in style

.card-module{ padding: 45rpx; display: flex; flex-direction: row; flex-wrap: wrap; The transform: translate3d (0, 0); .card{ width: 200rpx; height: 200rpx; line-height: 200rpx; text-align: center; color:#fff;
    margin: 10rpx;
    position:relative;
    overflow:hidden;
    .card-item{
      position:absolute;
      left:0;
      top:0;
      width:100%;
      height:100%;
      transition:all .5s ease-in-out;
      transform-style:preserve-3d;
      backface-visibility:hidden;
      box-sizing:border-box;
    }
    .front{
      background-color: red;
      transform: rotateY(0deg);
      z-index:2;
    }
    .back{
      background-color: #009fff;transform: rotateY(180deg); z-index:1; } } .card.change{ .front{ z-index:1; transform: rotateY(180deg); } .back{ z-index:2; transform: rotateY(0deg); }}}Copy the code

Results the following

There are some CSS properties that may need to be learned in large part

CSS 3 backface – visibility properties

Definitions and Usage

The backface-visibility property defines whether an element is visible when it is not facing the screen.

This property is useful if you do not want to see the back of a rotated element.

CSS 3 perspective properties

The Perspective property defines the distance, in pixels, of a 3D element from the view. This property allows you to change 3D elements to see the view of 3D elements.

When the Perspective attribute is defined for an element, its children get perspective, not the element itself.

Step 2: Shuffle the cards

Since the business is used by lottery, the scheme chosen is: after flipping, the card is returned to the middle of the middle card, and then the card is returned to its original position.

Primary framework on small programs have support animation interface, if not understand, please go to: developers.weixin.qq.com/miniprogram…

After having a basic understanding of animation, we can start to add scrambled animation on the basis of flipping. The animation interface of wechat applet is used by adding animation object on top of DOM object.

dom

<view class="card-module">
  <view class="card {{showClass ? 'change' : ''}} animation="{{cardItem.animationData}}" > front card-item">{{cardItem.front}} back card-item">{{cardItem.back}}   Copy the code

script

allMove() {/ / 110 is the width of the card and margins this. The methods, shuffle. Call (110).let timer = setTimeout(() => {
      clearTimeout(timer)
      this.methods.shuffle.call(this, 0)
      this.$apply()}, 1000)}, // shuffle (translateUnit) {let curCardData = this.cardData
    curCardData.map((item, index) => {
      let animation = wepy.createAnimation({
        duration: 500,
        timingFunction: 'ease'
      })
      animation.export()
      switch (index) {
        case 0:
          animation.translate(translateUnit, translateUnit).step()
          break
        case 1:
          animation.translate(0, translateUnit).step()
          break
        case 2:
          animation.translate(-translateUnit, translateUnit).step()
          break
        case 3:
          animation.translate(translateUnit, 0).step()
          break
        case 4:
          animation.translate(0, 0).step()
          break
        case 5:
          animation.translate(-translateUnit, 0).step()
          break
        case 6:
          animation.translate(translateUnit, -translateUnit).step()
          break
        case 7:
          animation.translate(0, -translateUnit).step()
          break
        case 8:
          animation.translate(-translateUnit, -translateUnit).step()
          break
      }
      item.animationData = animation.export()
    })
    this.cardData = curCardData
    this.$apply()},Copy the code

The algorithm needs to be optimized later, we first complete the functional effect,

Results the following

Step 3: Flip the cards

Dom code

<view class="card-module">
  <view class="card {{showClass ? 'change' : ''}} {{curIndex === index ? 'getprize' : ''}}" @tap="itemChage({{cardItem}}, {{index}})" animation="{{cardItem.animationData}}" >
    <view class="front card-item">{{cardItem.front}}</view>
    <view class="back card-item">{{cardItem.back}}</view>
  </view>
  </repeat>
</view>
Copy the code

The script code data defines an object with curIndex = -1

Data = {curOpen: -1,} methods = {itemChage (item, curIndex) {this.cardData[curIndex].front ='iphone x'
        console.log(item, curIndex)
        this.curOpen = curIndex
      }
}
Copy the code

less

.card.getprize{ .front{ z-index:2; transform: rotateY(0deg); } .back{ z-index:1; transform: rotateY(180deg); }}Copy the code

Results the following

Now we have the basic requirements; But the code in the displacement animation is too ugly. Let’s think about how to optimize the algorithm;

So we’re going to have a nine grid layout, which we can view as a two dimensional layout

resetData() {const total = 9 const lineTotal = 3 curcardData.map ((item, index) => {let curCardData = this.cardData
      let x = index % lineTotal
      let y = parseInt(index / lineTotal)
      item.twoArry = {x, y}
    })
}
Copy the code

Displacement is performed using the difference of the two dimensional layout in displacement animation

// shuffle (translateUnit) {let curCardData = this.cardData
    curCardData.map((item, index) => {
      let animation = wepy.createAnimation({
        duration: 500,
        timingFunction: 'ease'}) animation.export() const translateUnitX = translateUnit * (1 - item.twoArry.x) const translateUnitY = translateUnit *  (1 - item.twoArry.y) animation.translate(translateUnitX, translateUnitY).step() item.animationData = animation.export() }) this.cardData = curCardData this.$apply()},Copy the code

So the whole animation is complete, demo please go to github github.com/fishmankkk/…