ps:本次開(kāi)發(fā)基于wepy框架
由于最近接到一個(gè)需求--抽獎(jiǎng)活動(dòng);
翻牌打亂活動(dòng)抽獎(jiǎng)活動(dòng),大概需求是這樣的,九宮格卡牌,先正面展示所有獎(jiǎng)品,然后卡牌翻轉(zhuǎn),打亂排序,點(diǎn)擊卡牌,然后抽獎(jiǎng)。
這個(gè)需求本身其實(shí)不難,主要是分為三步;
我們先在dom中渲染9個(gè)卡牌。
<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> |
在數(shù)據(jù)中生成模擬卡牌數(shù)據(jù)
cardData: [ { animationData: {}, front: '正面1', back: '反面1' }, ... ... { animationData: {}, front: '正面9', back: '反面9' } ], showClass: false, |
在樣式中把卡牌的基本樣式渲染出來(lái)
.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屬性可能需要大部補(bǔ)充學(xué)習(xí)一下
css3 backface-visibility 屬性
定義和用法 backface-visibility 屬性定義當(dāng)元素不面向屏幕時(shí)是否可見(jiàn)。 如果在旋轉(zhuǎn)元素不希望看到其背面時(shí),該屬性很有用。
CSS3 perspective 屬性
perspective 屬性定義 3D 元素距視圖的距離,以像素計(jì)。該屬性允許您改變 3D 元素查看 3D 元素的視圖。 當(dāng)為元素定義 perspective 屬性時(shí),其子元素會(huì)獲得透視效果,而不是元素本身。
由于業(yè)務(wù)上是抽獎(jiǎng)使用的,所以選擇的方案是:翻轉(zhuǎn)后,卡牌收回到中間的卡牌中間,然后再讓卡牌回到原來(lái)的位置。 關(guān)于小程序的原生框架有支持的動(dòng)畫(huà)接口,若不了解的請(qǐng)前往: developers.weixin.qq.com/miniprogram… 在對(duì)動(dòng)畫(huà)有基本了解之后,我們可以開(kāi)始在翻轉(zhuǎn)的基礎(chǔ)上加上打亂的動(dòng)畫(huà)了 微信小程序的動(dòng)畫(huà)接口使用方式是在dom對(duì)象上面加上animation對(duì)象。 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() }, |
算法后面需要優(yōu)化,我們先完成功能效果, 效果如下
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中定義一個(gè)curIndex = -1的對(duì)象 data = { curOpen: -1, } methods = { // 抽獎(jiǎng) 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); } } |
效果如下
現(xiàn)在我們就已經(jīng)完成了基本的需求;但是在位移動(dòng)畫(huà)時(shí)候代碼寫(xiě)的太丑陋了。 我們來(lái)想想怎么優(yōu)化算法; 我們現(xiàn)在就九宮格布局,我們可以看成是二維布局
那我們是不是可以在卡牌中也使用二維數(shù)組布局屬性
resetData () { const total = 9 // 總數(shù) const lineTotal = 3 // 單行數(shù) curCardData.map((item, index) => { let curCardData = this.cardData let x = index % lineTotal let y = parseInt(index / lineTotal) item.twoArry = {x, y} }) } |
在位移動(dòng)畫(huà)中使用二維布局的差值進(jìn)行位移
// 洗牌 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() }, |
工作日 8:30-12:00 14:30-18:00
周六及部分節(jié)假日提供值班服務(wù)