天天看點

支付寶小程式中如何開發營銷元件

了解到要做的活動表現形式為老虎機,首先當然是google,百度跑跑找找demo,看下人家是怎麼實作的。

網上老虎機的插件挺多的,實作原理也各不一樣。

這裡先給個網上找的老虎機的效果demo:

老虎機效果demo

,效果是這麼個效果,但是咱們得了解原理吖,看了下源碼,jQuery做的?,小程式内又不能用jQuery,咋操作呢?

剖析了一波,劃重點(要考的):

css的 background-position屬性是設定背景圖像的起始位置,那麼我們控制背景圖在0-3秒的時間内顯示不同的位置,再加上過渡動畫就可以達到老虎機旋轉的效果

實作底部滾動停止後顯示彈窗且跟後端傳回的中獎碼一緻

先貼一段代碼

AXML
<view class="box-1">
    <view class="wheel-boxs">
      <view class="box-list" a:for="{{boxStatus}}" a:key="index">
        <view class="box-text" a:if="{{!isStart}}">{{item}}</view>
        <!-- 核心代碼 -->
        <view class="box-image" style="background: url('https://qiniu-image.qtshe.com/20181113wheels.png'); 
         background-position-y: {{isStart ? ((16 - item) * 100) + 1500 + 'rpx' : 0}}; background-size: 100% 100%; 
         transition-property: {{isStart ? 'all' : 'none'}}; transition-delay: {{(index + 1) * 100 + 'ms'}};
         transition-duration: 3.5s;">
        </view>
        {{item}}
      </view>
    </view>
    <view class="start-box">
        <view class="timeStemp" a:if="{{remainTime <= 3600}}">開獎倒計時: {{formatTime}}</view>
        <block a:else>
          <form onSubmit="startDraw" report-submit="true" a:if="{{pageVo.remainCount !== 0}}" >
            <button hover-class="none" formType="submit" class="animate-btn" />
          </form>
          <block a:else>
            <view class="no-draw" a:if="{{status.down>今日次數已用盡,明日再來</view>
            <view class="no-draw" a:else>請完成下方任務擷取次數</view>
          </block>
        </block>
    </view>
    <view class="last-tips" a:if="{{remainTime > 3600}}">目前剩餘 {{pageVo.remainCount || 0}} 次攢碼機會</view>
  </view>           
ACSS
.wheel-boxs {
  width: 680rpx;
  padding: 0 80rpx;
  margin-top: 16rpx;
}

.box-list {
  width: 90rpx;
  height: 100rpx;
  background: url(https://qiniu-image.qtshe.com/20190829openseason_03png) no-repeat center center;
  background-size: 100% 100%;
  display: inline-block;
  margin-right: 16rpx;
  overflow: hidden;
}

.box-list:last-child {
  margin-right: 0;
}

.box-tips {
  width: 500rpx;
  height: 54rpx;
  background: #ffcc1a;
  overflow: hidden;
  background-size: 100% 100%;
  margin: 20rpx auto;
  color: #7d2f0e;
  font-size: 24rpx;
  text-align: center;
  line-height: 54rpx;
  margin-top: 36rpx;
  border-radius: 54rpx;
}

.box-text {
  width: 100%;
  height: 100rpx;
  line-height: 100rpx;
  text-align: center;
  font-size: 44rpx;
  color: #FFF;
  font-weight: 600;
  font-family: 'HYRunYuanJ'
}

.box-image {
  height: 1500%;
}

.start-box {
  width: 100%;
  text-align: center;
  margin: 16rpx 0 8rpx;
}

.start-box button {
  width: 290rpx;
  height: 76rpx;
  background: url(https://qiniu-image.qtshe.com/20190829startDrawpng) no-repeat center center;
  background-size: 290rpx 76rpx;
  margin: 0 auto;
}

.timeStemp {
  margin: 24rpx auto 0;
  height: 80rpx;
  padding: 0 32rpx;
  line-height: 80rpx;
  text-align: center;
  color: #7d2f0e;
  background: url(https://qiniu-image.qtshe.com/20190829currt.png) no-repeat left top;
  background-size: 100% 100%;
  border-radius: 30rpx;
  font-size: 32rpx;
  display: inline-block;
}

.no-draw {
  height: 68rpx;
  font-size: 30rpx;
  text-align: center;
  color: #FFF;
  margin: 0 auto;
  border-radius: 68rpx;
  background: #9c9c9c;
  max-width: 400rpx;
  line-height: 68rpx;
}

.last-tips {
  width: 100%;
  text-align: center;
  color: #000;
  font-size: 24rpx;
}

.last-tips text {
  color: #f8294a;
}           
JS
var timer = null
var app = getApp()
Page({
  data: {
    season: 1, //目前是第幾場
    isStart: false, //是否開始抽獎
    isDialog: false, //是否顯示彈窗
    dialogId: 1, //顯示第幾個彈窗
    remainTime: 3600,
    formatTime: '60分00秒',
    pageVo: {}, //頁面基礎資料大對象
    boxTips: '本場開學碼将在9月30日 19:00截止領取', //頁面中部文案顯示
    typeTips: '9月30日20點開獎哦!',
    boxStatus: ['碼', '上', '有', '紅', '包'], //五個抽獎預設文案
    results: [], //抽中的碼
  },
  onLoad(options) {
    //引用外部字型
    my.loadFontFace({
      family: "HYRunYuanJ",
      source: 'url("https://qiniu-app.qtshe.com/HYRunYuanJ.ttf")'
    })
    my.showLoading({
      content: '加載中'
    })
  },
  onShow() {
    
  },
//格式化時間
  getdate(timeSteamp) {
    timeSteamp = new Date(timeSteamp)
    let m = timeSteamp.getMonth() + 1
    let d = timeSteamp.getDate()
    return (m < 10 ? "0" + m : m) + "月" + (d < 10 ? "0" + d : d) + "日"
  },
  //初始化頁面資料
  initData() {
    let postData = {
      id: 1
    }
    app.ajax(‘xxx’, postDat).then((res) => {
      my.hideLoading()
      if (res.success) {
        this.setData({
          pageVo: res.data
        })
      } else {
        util.toast(res.msg || '團團開小差啦,請稍後再試')
      }
    }, () => {
      my.hideLoading()
      util.toast('團團開小差啦,請稍後再試')
    })
  },
  //開始抽獎
  startDraw(e) {
  //收集一波formId
    util.addFormId(e.detail.formId)
    let postData = {
        season: this.data.pageVo.season
    }
    my.showLoading({
      content: '加載中'
    })
    app.ajax('xxx', postData).then((res) => { //發送請求給後端,拿到中獎碼
      my.hideLoading()
      if (res.success) {
        this.setData({
          isStart: true,
          results: res.data.result.split(','), //後端傳回的中獎碼
          dialogId: res.data.special ? 3 : 2  //顯示彈窗,如果有彩蛋顯示第三個彈窗,如果沒有顯示第二個彈窗
        })
        var t = setTimeout(() => {
          this.setData({
            isStart: false,
            isDialog: true, //顯示彈窗
            boxStatus: ['碼', '上', '有', '紅', '包'] //五個抽獎預設文案
          })
          clearTimeout(t)
          this.initData()
        }, 4000)  //頁面上内容滾動了4秒,這裡延時4秒
      } else {
        util.toast(res.msg || '團團開小差啦,請稍後再試')
      }
    }, () => {
      my.hideLoading()
      util.toast('團團開小差啦,請稍後再試')
    })
  },
  //倒計時日期格式化
  timestamp(time) {
    let min = Math.floor((time / 60) % 60)
    let sec = Math.floor(time % 60)
    min = min < 10 ? '0' + min : min
    sec = sec < 10 ? '0' + sec : sec
    this.setData({
      formatTime: `${min}分${sec}秒`
    })
  },
  //執行倒計時
  countDown(item) {
    clearInterval(timer)
    timer = setInterval(() => {
      if (item === 0) {
        this.initData()
        clearInterval(timer)
      } else {
        item -= 1
        this.timestamp(item)
      }
    }, 1000)
  },
  onShareAppMessage() {
    return {
      title: '“碼”上有紅包!點我瓜分10萬開學季禮金>>',
      path: 'xxx',
      bgImgUrl: 'https://qiniu-image.qtshe.com/20190829zfbshare.jpg'
    }
  },
  onHide() {
    clearInterval(timer)
  },
  onUnload() {
    clearInterval(timer)
  }
})
           

最後完整的實作效果在這裡:

微信小程式版

點我檢視完整的視訊效果

支付寶小程式版(看着效果卡頓,真機正常)

注意兩個點:

  • 旋轉的背景圖是雪碧圖。我這裡用到的是這張( https://qiniu-image.qtshe.com/20181113wheels.png )可供參考
  • 控制好圖的位移機關,需要計算下,這樣才可以讓後端傳回的值與你的圖相比對。我這裡是15個icon是以計算方式如下
<view class="box-image" style="
     background: url('https://qiniu-image.qtshe.com/20181113wheels.png'); 
     background-position-y: {{isStart ? ((16 - item) * 100) + 1500 + 'rpx' : 0}}; 
     background-size: 100% 100%; 
     transition-property: {{isStart ? 'all' : 'none'}}; 
     transition-delay: {{(index + 1) * 100 + 'ms'}}; 
     transition-duration: 3.5s;">
</view>           

這裡可以封裝成自定義元件,傳入圖檔以及數量即可。後面如果有再用到 我會封裝下再發出來。

最後說下彈窗顯示的圖的比對方法,根據圖檔大小計算,比較麻煩:

axml

<view class="ci-wrapper">
  <view a:if="{{icontype ==='nomal'}}" class="icon-default  icon-nomal" style=" background-position-y: {{(-24 -  117.86 * (typeId - 1)) + 'rpx'}};"></view>
  <view a:else class="icon-default  icon-fade" style=" background-position-y: {{(-20 - 110.73 * (typeId - 1)) + 'rpx'}}; "></view>
</view>           

acss

.ci-wrapper {
}
.icon-default {
  width: 70rpx;
  height: 70rpx;
  background-repeat: no-repeat;
 
}
.icon-nomal {
  background-image: url(https://qiniu-image.qtshe.com/20181113wheels.png);
  background-position-x: -17rpx;
   background-size: 100rpx 1768rpx
}
.icon-fade {
  background-image: url(https://qiniu-image.qtshe.com/20181113wheels_fade.png);
  background-size: 110rpx 1661rpx;
  background-position-x: -18rpx;
}
           

Js

Component({
  props: {
    icontype: 'nomal',
    iconid: 1
  },
  data: {
    nomalOrigin: {
      x: -17,
      y: -24
    },
    fadeOrigin: {
      x: -17,
      y: -24
    },
    typeId: 1
  }
})           

以上就是一個完整小程式的老虎機實作方案,有什麼優化點大家可以指出來,後續會整理一下出個檔案拷貝就可使用。

因為支付寶端,暫無代碼片段功能,是以寫了個微信小程式版本的代碼片段:

https://developers.weixin.qq.com/s/1k5eSnmh7z72

繼續閱讀