微信小程式抽獎-翻牌

fishman發表於2018-08-30

背景

ps:本次開發基於wepy框架

由於最近接到一個需求--抽獎活動;

翻牌打亂活動抽獎活動,大概需求是這樣的,九宮格卡牌,先正面展示所有獎品,然後卡牌翻轉,打亂排序,點選卡牌,然後抽獎。

這個需求本身其實不難,主要是分為三步;

  • 展示所有卡牌,然後翻轉。
  • 打亂所有卡牌
  • 點選其中一張卡牌,抽獎

第一步:卡牌翻轉

我們先在dom中渲染9個卡牌。

<view class="card-module">
  <view class="card {{showClass ? 'change' : ''}}>
    <view class="front card-item">{{cardItem.front}}</view>
    <view class="back card-item">{{cardItem.back}}</view>
  </view>
  </repeat>
</view>
複製程式碼

在資料中生成模擬卡牌資料

cardData: [
    {
      animationData: {},
      front: '正面1',
      back: '反面1'
    },
    ...
    ...
    {
      animationData: {},
      front: '正面9',
      back: '反面9'
    }
  ],
  showClass: false,
複製程式碼

在樣式中把卡牌的基本樣式渲染出來

.card-module{
  padding: 45rpx;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  transform:translate3d(0,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);
    }
  }
}
複製程式碼

效果如下

微信小程式抽獎-翻牌

這裡有些css屬性可能需要大部補充學習一下

css3 backface-visibility 屬性

定義和用法

backface-visibility 屬性定義當元素不面向螢幕時是否可見。

如果在旋轉元素不希望看到其背面時,該屬性很有用。

CSS3 perspective 屬性

perspective 屬性定義 3D 元素距檢視的距離,以畫素計。該屬性允許您改變 3D 元素檢視 3D 元素的檢視。

當為元素定義 perspective 屬性時,其子元素會獲得透視效果,而不是元素本身。

第二步:卡牌打亂

由於業務上是抽獎使用的,所以選擇的方案是:翻轉後,卡牌收回到中間的卡牌中間,然後再讓卡牌回到原來的位置。

關於小程式的原生框架有支援的動畫介面,若不瞭解的請前往: developers.weixin.qq.com/miniprogram…

在對動畫有基本瞭解之後,我們可以開始在翻轉的基礎上加上打亂的動畫了 微信小程式的動畫介面使用方式是在dom物件上面加上animation物件。

dom

<view class="card-module">
  <view class="card {{showClass ? 'change' : ''}} animation="{{cardItem.animationData}}" >
    <view class="front card-item">{{cardItem.front}}</view>
    <view class="back card-item">{{cardItem.back}}</view>
  </view>
  </repeat>
</view>
複製程式碼

script

allMove () {
    // 110 是卡牌寬度加邊距
    this.methods.shuffle.call(this, 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()
},
複製程式碼

演算法後面需要優化,我們先完成功能效果,

效果如下

微信小程式抽獎-翻牌

第三步:卡牌翻轉

dom程式碼

<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>
複製程式碼

script程式碼
data中定義一個curIndex = -1的物件

data = {
      curOpen: -1,
      }
methods = {
    // 抽獎
      itemChage (item, curIndex) {
        this.cardData[curIndex].front = 'iphone x'
        console.log(item, curIndex)
        this.curOpen = curIndex
      }
}
複製程式碼

less

.card.getprize{
    .front{
      z-index:2;
      transform: rotateY(0deg);
    }
    .back{
      z-index:1;
	    transform: rotateY(180deg);
    }
  }
複製程式碼

效果如下

微信小程式抽獎-翻牌

現在我們就已經完成了基本的需求;但是在位移動畫時候程式碼寫的太醜陋了。
我們來想想怎麼優化演算法;

我們現在就九宮格佈局,我們可以看成是二維佈局

微信小程式抽獎-翻牌
那我們是不是可以在卡牌中也使用二維陣列佈局屬性

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}
    })
}
複製程式碼

在位移動畫中使用二維佈局的差值進行位移

// 洗牌
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()
},
複製程式碼

這樣整個動畫就算完成了, demo請前往github github.com/fishmankkk/…

相關文章