抽獎動畫 - 開寶箱抽獎


1. 需求

開寶箱在一些商家營銷活動中也很常見,這個需求簡單,產品經理說就是做個動畫就好,那我們就可以自由發揮了。高保圖如下圖1.
image
圖1
開局一張圖,剩下的全靠自己編了,動作怎么動,先看看UI給的素材,看米下鍋。一張關閉的箱子圖片,如下圖2
image
圖2
一張打開的箱子,如下圖3
image
圖3
一張獎品背景圖片,是光芒,可以作為獎品的背景圖,如下圖4
image
圖4

雖然需求文檔中沒有給出這個動畫的具體需求,但可以根據產品的描述,可以把需求歸納一下,如下:

  1. 點擊“立即開啟”,先顯示半透明的蒙版,再顯示關閉的箱子,並且從小變大
  2. 請求接口,同時從關閉變成打開的箱子,在打開箱子的空白處顯示中獎結果
  3. 用光芒圖片作為獎品圖片的背景,並且光芒不斷地旋轉起來
  4. 點擊關閉,關閉整個中獎彈框

2. 思路

這個動畫相對簡單,可以直接使用css中的animation動畫,通過keyframe定義動畫幀來讓圖片從小變大,同時切換上面的圖2和圖3可以讓寶箱狀態從關閉變成打開,然后顯示獎品就有了。然后還有一個地方,就是獎品的背景是一個圓形光芒,可以讓它旋轉,或者不斷地變大變小,這樣看起來更加的生動。

3. 實現過程

3.1 蒙版

點擊按鈕首先彈出蒙版,這就沒啥好說的了,使用fix定位 + background + opacity可以做一個簡單的蒙版,代碼如下:

<!-- 抽獎按鈕 -->
<img class="treasure" src="./../assets/images/treasurebox.gif" @click="openBox" alt=""/>
<!-- 彈出層 -->
<div v-if="showBox" class="pop-up">
<div class="prize-box"></div>

css代碼如下:

.pop-up {
  position: fixed;
  z-index: 4;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.4);
}

注意上面代碼中使用rgba作為背景色,最后一個參數是opacity,規定不透明度。從 0.0 (完全透明)到 1.0(完全不透明)。

3.2 開寶箱

寶箱圖片有2個,一個是關閉的,一個是打開的,要用一個動畫控制二者切換,並且還要掌握好他們的顯示時間這樣看起來是一個打開的過程,不過這里只有兩張圖片,無法看到打開過程,只能稍微模擬一下。如果要有整個過程的話,就要提供很多個中間狀態的寶箱圖片了。html代碼如下:

<div v-if="showBox" class="pop-up">
  <div class="prize-box">
  </div>
</div>

css代碼如下:

$aniDuration: 2s;
.prize-box {
  position: relative;
  width: 548px;
  height: 739px;
  margin: 81px auto auto auto;
  animation: openBox $aniDuration ease-out 1s 1 forwards;
  background: top/5% no-repeat url("./../assets/images/box@2x.png");
}
@keyframes openBox {
  from {
      background-position: center;
      -webkit-background-size: calc(548px * 0.1) calc(739px * 0.1);
      background-size: 5%;
      width: calc(548px * 0.1);
      height: calc(739px * 0.1);
      background-image: url("./../assets/images/box@2x.png");
      background-position: top;
  }
  50% {
      background-position: center;
      background-size: 50%;
      width: calc(548px * 0.5);
      height: calc(739px * 0.5);
      background-image: url("./../assets/images/box@2x.png");
      background-position: top;
  }
  80% {
      background-position: center;
      background-size: 110%;
      width: calc(548px * 1.1);
      height: calc(739px * 1.1);
      background-position: top;
  }
  to {
      background-position: center;
      background-size: 548px 739px;
      width: 548px;
      height: 739px;
      background-image: url("./../assets/images/boxopen@2x.png");
      background-position: top;
  }
}

代碼中給class為prize-box的容器定義了一個動畫openBox,用變量$aniDuration紀錄動畫持續時長,1秒后開始執行,最后停留在終態,時間函數(animation-timing-function)使用easy-out。在keyframe關鍵幀中修改了背景圖片大小,dom容器大小等css屬性,都是從小到大,並且在動畫的0%80%部分是顯示關閉寶箱,最后80%100%顯示開啟的寶箱。在動畫的80%處背景稍微變大一下,看起來有膨脹的效果。可以想想一下,這個動畫的整個過程是,關閉寶箱從小到大,變成開啟的寶箱,並且膨脹一下,最后恢復到原始大小。

animation的第三個屬性animation-timing-function是一個貝塞爾時間函數,可用的取值如下:

  1. linear
    動畫以恆定速度運行。此關鍵詞表示緩沖函數 cubic-bezier(0.0, 0.0, 1.0, 1.0)。如下圖5。
    image
    圖5
  2. ease
    動畫緩慢開始,然后突然加速,最后緩慢移向目標。此關鍵詞表示緩沖函數cubic-bezier(0.25, 0.1, 0.25, 1.0)。它與 ease-in-out 類似,但它在開始時加速更快。如下圖6。
    image
    圖6
  3. ease-in
    動畫緩慢開始,然后逐漸加速直到結束,在結束點時突然停止。此關鍵詞表示緩沖函數 cubic-bezier(0.42, 0.0, 1.0, 1.0),如下圖7。
    image
    圖7
  4. ease-in-out
    動畫緩慢開始,然后加速,最后減速直至結束。此關鍵詞表示緩沖函數 cubic-bezier(0.42, 0.0, 0.58, 1.0)。開始時,其表現與 ease-in 函數類似;結束時,與 ease-out 函數類似。如下圖8。
    image
    圖8
  5. ease-out
    此動畫突然開始,然后逐漸減速直至結束。此關鍵詞表示緩沖函數 cubic-bezier(0.0, 0.0, 0.58, 1.0)。如下圖9。
    image
    圖9

貝塞爾時間函數的內容很多,並且很晦澀,這里不再展開討論。看看效果,如下圖10

圖10

3.3 請求接口

請求接口前需要定義好獎品,以便從接口中取出中獎獎品信息,代碼如下:

data() {
  return {
    showBox: false,
    showPrize: false,
    prizeList: [
      {prizeId: "100860801", prizeName: "100元滿減券"},
      {prizeId: "100860802", prizeName: "20元抵扣劵",},
      {prizeId: "100860803", prizeName: "10元抵扣券"},
      {prizeId: "100860804", prizeName: "1個月優惠員"},
      {prizeId: "100860805", prizeName: "1元紅包"},
      {prizeId: "100860806", prizeName: "5紅包"},
      {prizeId: "100860807", prizeName: "1元抵扣券"},
      {prizeId: "100860808", prizeName: "500元滿減券"},
      {prizeId: "100860809", prizeName: "200元滿減券"}
    ],
    title: ['發送給好友', '可增加一次開寶箱機會'],
    actionBtn: {id: 1, title: '呼朋喚友,再開一次'},
    prizeData: {prizeId: "100860801", prizeName: "100元移動話費"},      //抽獎信息獎信息
  }
}

這里依然使用getRandomIntInclusive()方法從獎品數據中隨機取出一個獎品,模擬抽獎過程。代碼如下:

/* 開寶箱抽獎 */
openBox() {
  this.showBox = true
  setTimeout(() =>  {
    this.showPrize = true
    let index = this.getRandomIntInclusive(0, this.prizeList.length - 1)
    this.prizeData = this.prizeList[index]
  }, 3000)
},
/* 關閉按鈕 */
followAction() {
  this.showBox = false
  this.showPrize = false
},
//返回隨機數,大於等於min,小於等於max
getRandomIntInclusive(min, max) {
  min = Math.ceil(min)
  max = Math.floor(max)
  return Math.floor(Math.random() * (max - min + 1)) + min //含最大值,含最小值 
}

3.4 顯示獎品

開寶箱的動畫有了,剩下的就是請求接口,顯示獎品了。注意開啟的寶箱有兩處留白,這里要使用相對定位來固定獎品圖片,獎品名稱文案,抽獎提示文案,如下圖11
image
圖11

html代碼如下:

<!-- 彈出層 -->
<div v-if="showBox" class="pop-up">
  <div class="prize-box">
    <template v-if="showPrize">
      <div class="prize">
        <img :src="require('./../assets/images/prize/' + prizeData.prizeId + '.png')" alt="" class="img-prize"/>
      </div>
      <div class="prizetip">
        <div>恭喜獲您獲得{{ prizeData.prizeName }}</div>
      </div>
      <div class="prizelead">
        <div class="content" @click="followAction">
          {{ actionBtn.title }}&gt;
        </div>
      </div>
    </template>
  </div>
  <img v-if="showPrize" class="close" src="./../assets/images/closebox@2x.png" @click="followAction" alt=""/>
</div>

css代碼如下:

// 獎品
.prize {
  z-index: 5;
  position: absolute;
  left: 50%;
  margin-left: -118px;
  top: 190px;
  left: 50%;
  width: 219px;
  height: 219px;
  background-size: 219px 219px;
  background-position: center;
  align-content: center;
  display: flex;
  align-items: center;
  justify-content: center;
  .img-prize {
      width: 180px;
      height: 150px;
      z-index: 6;
  }
}
.prize:before {
  content: "";
  position: absolute;
  z-index: 4;
  width: 110%;
  height: 110%;
  background: center / contain no-repeat url("../assets/images/prizebg@2x.png");
  animation: turn 6s linear infinite;
}
@keyframes turn{
  0% { -webkit-transform: rotate(0deg); }
  100%{ -webkit-transform: rotate(360deg); }
}
.prizetip {
  z-index: 6;
  position: relative;
  top: 380px;
  margin: 0 auto;
  font-size: 28px;
  font-family: HuipuMR;
  color: rgba(51, 51, 51, 1);
  height: 72px;
  @include flex(center, center, column, nowrap);
  div {
      height: 40px;
      line-height: 40px;
  }
}
.prizelead {
  position: relative;
  top: 525px;
  margin: 0 auto;
  max-width: 374px;
  height: 70px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(90deg, rgba(247, 231, 165, 1) 0%, rgba(255, 234, 114, 1) 100%);
  box-shadow: 0px 4px 8px 0px rgba(203, 68, 15, 1);
  border-radius: 40px;
  .content {
    text-align: center;
    font-size: 28px;
    color: rgba(191, 62, 11, 1);
    line-height: 38px;
    text-shadow: 0px 4px 8px rgba(203, 68, 15, 1);
  }
}

注意,顯示了獎品之后我們還在獎品的背景,光芒四射圖片上設置了一個旋轉動畫,這個相對簡單,就是設置rotate從0deg到360deg。並且把這個背景使用了before偽類,這樣就不用再弄一個dom層了。

在最后加了一個關閉按鈕,這個不再贅述。

看下效果,如下圖12
image
圖12

4. 總結

本文介紹了如何使用css的animation動畫實現一個開寶箱抽獎的功能,主要就是animation+keyframe,相對簡單。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM