13
收藏

如何实现一个小程序版本的老虎机

简单介绍下老虎机实现原理。

运营:咱们最近需要拉新用户,做个简单点的活动,就老虎机形式吧。
产品:老虎机的话比较简单,网上demo那么多随便拷贝拷贝就能用啦。
开发:你来做。

进入正题:

网上老虎机的插件挺多的,实现原理也各不一样,
然后这里主要提下自己当初做老虎机抽奖活动时想到的一个原理:

划重点啦:
css的 background-position属性是设置背景图像的起始位置,那么我们控制背景图在0-3秒的时间内显示不同的位置,再加上过渡动画就可以达到老虎机旋转的效果

第一个版本的在 这里 vue的版本
看下效果视频(第二个版本)
markdown只能上传图片 - -然后我视频转的gif有十多兆,放这里有点卡。就上传视频了。
视频效果
该版本定时4秒停再弹窗,比较突兀,未做到老虎机底部滚动停止后再显示弹窗。

今天要说的是第三种方案(实现底部滚动停止后显示弹窗且跟后端返回的中奖码一致)
直接上代码

WXML
<view class="box-container">
  <view class="box-tips">{{boxTips}}</view>
  <view class="wheel-boxs">
    <view class="box-list" wx:for="{{boxStatus}}" wx:key="index">
      <view class="box-text" wx: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">
   <form bindsubmit="startDraw" report-submit="true" wx:if="{{pageVo.remainCount !== 0}}">
       <button class="start-draw" formType="submit" />
   </form>
  </view>
  <view class="last-tips">当前剩余 <text>{{pageVo.remainCount || 0}}</text> 次攒码机会</view>
</view>
WXSS
.box-container {
  width: 680rpx;
  height: 380rpx;
  background: url(https://qiniu-image.qtshe.com/20190227goddess_02.png) no-repeat center center;
  background-size: 100% 100%;
  position: relative;
  z-index: 10;
  margin: auto;
  overflow: hidden;
}    
.wheel-boxs {
  width: 680rpx;
  padding: 0 80rpx;
  margin-top: 16rpx;
}    
.box-list {
  width: 90rpx;
  height: 100rpx;
  background: url(https://qiniu-image.qtshe.com/20190227goddess_11.png) 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: url(https://qiniu-image.qtshe.com/20190227goddess_10.png) no-repeat center center;
  overflow: hidden;
  background-size: 100% 100%;
  margin: 20rpx auto;
  color: #000;
  font-size: 24rpx;
  text-align: center;
  line-height: 54rpx;
  margin-top: 36rpx;
}    
.box-text {
  width: 100%;
  height: 100rpx;
  line-height: 100rpx;
  text-align: center;
  font-size: 44rpx;
  color: #f8294a;
  font-weight: 600;
}    
.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/20190227startDraw.png) no-repeat center center;
  background-size: 290rpx 76rpx;
  margin: 0 auto;
}
.start-box .start-draw {
  width: 290rpx;
  height: 76rpx;
  background: url(https://qiniu-image.qtshe.com/20190227startDraw.png) no-repeat center center;
  background-size: 290rpx 76rpx;
  margin: 0 auto;
}
JS
const app = getApp()
Page({
  data: {
    isStart: false, //是否开始抽奖
    isDialog: false, //是否显示中奖弹窗
    dialogId: 1, //显示第几个中奖弹窗
    boxTips: '本场女神码将在3月8日 19:00截止领取', //页面中部文案显示
    typeTips: '3月8日20点开奖哦!',
    boxStatus: ['码', '上', '有', '红', '包'], //五个抽奖默认文案
    results: [], //抽中的码
  },
  onLoad() {
      this.initData()
  },
  //显隐藏中奖弹窗或规则弹窗等
  handleModel() {
    this.setData({
      isDialog: !this.data.isDialog
    })
  },
  onShow() {},
  //初始化页面数据
  initData() {
    let postData = {
      url: 'xxx'
    }
    app.ajax(postData).then((res) => {
      if (res.success) {
        this.setData({
          pageVo: res.data  //页面所有数据
        })
      } else {
        util.toast( res.msg || '团团开小差啦,请稍后再试')
      }
    }, () => {
      wx.hideLoading()
      util.toast( '团团开小差啦,请稍后再试')
    })
  },
  //收集FormId 发模版消息用
  addFormId(e) {
    if (e.detail.formId !== 'the formId is a mock one') { //开发者工具上显示这段文案,过滤掉
      let formData = {
        url: 'xxx',
        data: {
          formId: e.detail.formId,
          openId: wx.getStorageSync('openId') || ''
        }
      }
      app.ajax(formData)
    }
  },
  //开始抽奖
  startDraw(e) {
  //这里可以做下节流
    this.addFormId(e)  //收集formId
    let postData = {
      url: 'xxx'
    }
    app.ajax(postData).then((res) => {
      if (res.success) {
        this.setData({
          isStart: true,
          results: res.data.result.split(','), //假如后端返回[1,2,3,4,5]
          dialogId: res.data.special ? 3 : 2  //3为彩蛋状态,2为普通状态
        })
      } else {
        util.toast(res.msg || '团团开小差啦,请稍后再试')
      }
    }, () => {
      wx.hideLoading()
      util.toast( '团团开小差啦,请稍后再试')
    })
  },   
  onShareAppMessage() {
    return {
      title: '码上有红包!点我瓜分10万女神节礼金!',
      path: '/activity/xxx/xxx',
      imageUrl: 'https://qiniu-image.qtshe.com/20190227goddess-share.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>
    

这里可以封装成自定义组件,传入图片以及数量即可。后面如果有再用到 我会封装下再发出来。

最后说下弹窗显示的图的匹配方法,根据图片大小计算,比较麻烦:

WXML
 <view class="ci-wrapper">
    <view wx:if="{{icontype ==='nomal'}}" class="icon-default  icon-nomal" style=" 
  	  background-position-y: {{(-24 -  117.86 * (typeId - 1)) + 'rpx'}};">
    </view>
    <view wx:else class="icon-default  icon-fade" style=" 
    	background-position-y: {{(-20 - 110.73 * (typeId - 1)) + 'rpx'}}; ">
    </view>
 </view>
WXSS
.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({
    properties: {
      icontype: {
        type: String,
        value: "nomal"
      },
      iconid: {
        type: Number,
        value: 1,
        observer(newVal, oldVal) {
          this.setData({ typeId: newVal });
        }
      }
    },
    data: {
      nomalOrigin: {
         x: -17,
         y: -24
      },
      fadeOrigin: {
        x: -17,
        y: -24
      },
      typeId: 1
    }
  })

至于引用的的地方嘛,就这样操作(resultList为中奖数字的数组):

<code-icon wx:for="{{resultList}}" icontype="nomal" iconid="{{item}}" wx:key="{{index}}"></code-icon>

以上就是一个完整小程序的老虎机实现方案,有什么优化点大家可以指出来。

最后写了个代码片段:https://developers.weixin.qq.com/s/1k5eSnmh7z72

最后一次编辑于  04-08  (未经腾讯允许,不得转载)
收藏赞 13

8 个评论

  • G.Y
    G.Y

    厉害了,学习,

    赞同 1没有帮助
    评论 2
    复制
    05-05
    • 要么胖要么更胖🌼
      要么胖要么更胖🌼

      😂欢迎使用。有问题及时沟通。

      赞同 1没有帮助
      回复
      复制
      05-05
    • G.Y
      G.Y
      回复要么胖要么更胖🌼

      好的

      赞同 1没有帮助
      回复
      复制
      05-05
    评论
  • 无

    感谢分享!!~OvO

    赞同 0没有帮助
    评论 1
    复制
    04-24
    • 要么胖要么更胖🌼
      要么胖要么更胖🌼

      😂欢迎使用。有问题及时沟通。

      赞同 0没有帮助
      回复
      复制
      04-24
    评论
  • 要么胖要么更胖🌼
    要么胖要么更胖🌼

    这也是用自己想的方法写的大转盘 有点low 不要嫌弃 😂 代码片段:https://developers.weixin.qq.com/s/xqJPALmr767K

    赞同 0没有帮助
    评论 0
    复制
    04-20
  • 抬头忘了谁
    抬头忘了谁

    iPhone 5 好像没对齐..

    赞同 0没有帮助
    评论 1
    复制
    04-08
    • 要么胖要么更胖🌼
      要么胖要么更胖🌼

      是ui样式有问题么

      赞同 0没有帮助
      回复
      复制
      04-08
    评论
  • Mr.G
    Mr.G

    关键是老虎机这类程序,在小程序里面是非法的吧。

    赞同 0没有帮助
    评论 3
    复制
    04-05
    • 要么胖要么更胖🌼
      要么胖要么更胖🌼

       不是非法的哈,你看效果。

      赞同 0没有帮助
      回复
      复制
      04-05
    • Mr.G
      Mr.G
      回复要么胖要么更胖🌼

      不错~动画效果挺好

      赞同 0没有帮助
      回复
      复制
      04-05
    • 要么胖要么更胖🌼
      要么胖要么更胖🌼
      回复Mr.G

      嗯,不是赌博啥的,只是给运营做抽奖活动用的。

      赞同 0没有帮助
      回复
      复制
      04-08
    评论
  • 一捧阳光
    一捧阳光

    sixsixsix

    赞同 0没有帮助
    评论 1
    复制
    04-04
    • 要么胖要么更胖🌼
      要么胖要么更胖🌼

      有尝试吗?

      赞同 0没有帮助
      回复
      复制
      04-04
    评论
  • samkee😁
    samkee😁

    写的挺好

    赞同 0没有帮助
    评论 1
    复制
    04-04
    评论
  • 管凯旋
    管凯旋

    [捂脸]你把老虎机改成转盘抽奖是不是好一点呢


    赞同 0没有帮助
    评论 6
    复制
    04-04
    评论