美文网首页
小程序 大转盘 抽奖 canvas animation

小程序 大转盘 抽奖 canvas animation

作者: 悟空_大师兄_ | 来源:发表于2020-05-07 12:10 被阅读0次

    项目需求运用到大转盘 可设置概率 可直接自定义结果 效果如下 

    两种方法及结合法

    一 通过canvas 实现 但是因为定时器原因 手机端卡顿严重 故而最终使用了方法二 但也是该记录下 学习canvas

    二 通过小程序Api animation完成完美解决卡顿问题 更精确定位 有样式缺陷 css无法解决样式 自动分配问题 故结合一二两种方法 出现第三种

    三 通过小程序Api animation 做动画旋转 样式用canvas来实现 完美解决各类问题 

    话不多说踩坑部分 就不展示 直接上第三种方法

    创建动画区域 (animation) 动画可参考小程序官方API animationData动画参数 在点击开始的时候填充数据

    <view class="wrapper-content" style='margin:0 auto;'>

      <view class="canvas-container">

        <view animation="{{animationData}}" class="canvas-content" style='margin:0 auto;'>   

        </view>

      </view>

    </view>

    .wrapper-content{

      background: #E0CFBC;

      border-radius: 50%;

      width: 720rpx;

      height: 720rpx;

      padding: 40rpx;

      position: relative;

      box-sizing: border-box;

      z-index: 101;

    }

    .canvas-container {

      margin: 0 auto;

      position: absolute;

      left: 40rpx;

      top: 40rpx;

      width: 640rpx;

      height: 640rpx;

      border-radius: 50%;

    }

    .canvas-content {

      overflow: hidden;

      box-sizing: content-box;

      border: 20rpx solid #CDB193;

      position: absolute;

      left: 0;

      top: 0;

      z-index: 1;

      display: block;

      width: 600rpx;

      height: 600rpx;

      border-radius: inherit;

      background-clip: padding-box;

    }

    定义canvas 画板区域  设置ID 

    <canvas class="canvas-line" disable-scroll="true" canvas-id="canvas"></canvas>

    onReady: function(e) {

        let that = this,

            fps = 60,

            awardsConfig = that.data.awardsConfig,

            w = this.data.windowWidth / 750 * 600,

            h = this.data.windowWidth / 750 * 600,

            context = wx.createCanvasContext('canvas'),

            //定义canvas位置

            wheel = new Wheel(w / 2, w / 2, (w / 2) - 0, awardsConfig.slicePrizes),

            animation = new Animation(wheel, { w: w, h: h });

            wheel.prizeWidth = 30;

            wheel.prizeHeight = 30;

        // 更新动画

        let update = function () {

          // 清空

          context.clearRect(0, 0, w, h);

          // 画转盘

          wheel.draw(context);

          // 更新数据

          animation.draw(context);

          // 更新数据

          animation.update();

          // 绘图 

          context.draw()

        };

        setTimeout(update, 1000 / fps, 1000 / fps)

    }

    1.awardsConfig.slicePrizes为奖品列表  因为大转盘是圆的 所以W H 是一样的 

    2.this.data.windowWidth 是屏幕的宽度 小程序有API 可以获取  600是设置的转盘内容(canvas)的rpx宽度  用屏幕宽度/750*设置内容宽度rpx = 实际内容宽度的px 值

    3.wheel是canvas绘制转盘的代码 可自行修改参数

    设置点击抽奖按钮 两种方法 一直接在canvas内绘制  二在HTML里面通过定位实现

    提供二 HTML 定位实现按钮

    <view class="canvas-btn" bindtap="getLottery">

            <view>

                <view style="font-size:56rpx;color:#fff;padding-bottom:4rpx;">开始</view>

                <view style="font-size:20rpx;color:#6F5942;font-weight:600;">点击抽奖</view>

              </view>

    </view>

    .canvas-btn {

      display: flex;

      flex-direction: column;

      justify-content: space-around;

      position: absolute;

      left: 50%;

      top: 50%;

      margin-left: -110rpx;

      margin-top: -110rpx;

      z-index: 400;

      width: 220rpx;

      height: 220rpx;

      border-radius: 50%;

      color: #f4e9cc;

      border: 10px solid #cdb193;

      text-align: center;

      font-size: 40rpx;

      text-decoration: none;

      box-sizing: border-box;

    }

    .canvas-btn>view {

      position: absolute;

      top: 7%;

      left: 7%;

      width: 86%;

      height: 86%;

      border-radius: 50%;

      box-sizing: border-box;

      padding: 22rpx 20rpx 0;

      background: linear-gradient(134deg, rgba(232, 219, 197, 1) 0%, rgba(205, 177, 147, 1) 100%);

      /* box-shadow:0px 5px 7px 0px rgba(255,255,255,1); */

      margin: auto;

      z-index: 102;

    }

    .canvas-btn::after {

      position: absolute;

      display: block;

      content: ' ';

      left: 39%;

      top: -78%;

      width: 0;

      height: 0;

      overflow: hidden;

      border-width: 80rpx 20rpx 80rpx 20rpx;

      border-style: solid;

      border-color: transparent;

      border-bottom-color: #ffab52;

    }

    getLottery() {

        let that = this;

        // 获取奖品配置

        let awardsConfig = that.data.awardsConfig,

            runNum = 12, len = awardsConfig.slicePrizes.length,

            awardIndex = 0;

        awardIndex = parseInt(Math.random() * 6)

        console.log("奖品序号:" + awardIndex);

        // 旋转抽奖

        app.runDegs = app.runDegs || 0

        app.runDegs = app.runDegs + (360 - app.runDegs % 360) + (360 * runNum - awardIndex * (360 / len))

        //创建动画

        let animationRun = wx.createAnimation({

          duration: 4000,

          timingFunction: 'ease'

        })

        console.log(awardsConfig.slicePrizes[awardIndex]);

        that.animationRun = animationRun

        animationRun.rotate(app.runDegs - (360 / len * 2 + (360 / len)) ).step()

        that.setData({

          animationData: animationRun.export()

        })

      },

    点击按钮触发getLottery 进行动画数据填充 实现旋转效果  runNum为旋转的圈数 awardIndex为中奖的序号

    整体如此完美实现献上整体代码

    html

    <view class="wrapper-content" style='margin:0 auto;'>

              <view class="canvas-container-quiu" wx:for="{{list}}" style="-webkit-transform: rotate({{index * (360/list.length)}}deg);transform: rotate({{index * (360/list.length)}}deg);{{index%2==0?'background:#F2E86D':'background:#ffffff'}}"></view>

              <view class="canvas-container">

                <view animation="{{animationData}}" class="canvas-content" style='margin:0 auto;'>

                <canvas class="canvas-line" disable-scroll="true" bindtouchstart="canvasTouchStart" bindtouchmove="touchMove" bindtouchend="canvasTouchEnd" canvas-id="canvas"></canvas>

                </view>

                <view class="canvas-btn" bindtap="getLottery">

                  <view>

                    <view style="font-size:56rpx;color:#fff;padding-bottom:4rpx;">开始</view>

                    <view style="font-size:20rpx;color:#6F5942;font-weight:600;">点击抽奖</view>

                  </view>

                </view>

              </view>

            </view>

    CSS

    .wrapper-content{

      background: #E0CFBC;

      border-radius: 50%;

      width: 720rpx;

      height: 720rpx;

      padding: 40rpx;

      position: relative;

      box-sizing: border-box;

      z-index: 101;

    }

    .canvas-container ul, .canvas-container li {

      margin: 0;

      padding: 0;

      list-style: none;

    }

    .canvas-container {

      margin: 0 auto;

      position: absolute;

      left: 40rpx;

      top: 40rpx;

      width: 640rpx;

      height: 640rpx;

      border-radius: 50%;

    }

    .canvas-container-quiu{

      width: 20rpx;

      height: 20rpx;

      border-radius: 50%;

      position: absolute;

      left:10rpx;

      top: 50%;

      margin-top: -8rpx;

      -webkit-transform-origin: 330rpx 50%;

      transform-origin: 350rpx 50%;

      z-index: 1001;

    }

    .canvas-content {

      overflow: hidden;

      box-sizing: content-box;

      border: 20rpx solid #CDB193;

      position: absolute;

      left: 0;

      top: 0;

      z-index: 1;

      display: block;

      width: 600rpx;

      height: 600rpx;

      border-radius: inherit;

      background-clip: padding-box;

    }

    .canvas-btn {

      display: flex;

      flex-direction: column;

      justify-content: space-around;

      position: absolute;

      left: 50%;

      top: 50%;

      margin-left: -110rpx;

      margin-top: -110rpx;

      z-index: 400;

      width: 220rpx;

      height: 220rpx;

      border-radius: 50%;

      color: #f4e9cc;

      border: 10px solid #cdb193;

      text-align: center;

      font-size: 40rpx;

      text-decoration: none;

      box-sizing: border-box;

    }

    .canvas-btn>view {

      position: absolute;

      top: 7%;

      left: 7%;

      width: 86%;

      height: 86%;

      border-radius: 50%;

      box-sizing: border-box;

      padding: 22rpx 20rpx 0;

      background: linear-gradient(134deg, rgba(232, 219, 197, 1) 0%, rgba(205, 177, 147, 1) 100%);

      /* box-shadow:0px 5px 7px 0px rgba(255,255,255,1); */

      margin: auto;

      z-index: 102;

    }

    .canvas-btn::after {

      position: absolute;

      display: block;

      content: ' ';

      left: 39%;

      top: -78%;

      width: 0;

      height: 0;

      overflow: hidden;

      border-width: 80rpx 20rpx 80rpx 20rpx;

      border-style: solid;

      border-color: transparent;

      border-bottom-color: #ffab52;

    }

    js

    var app = getApp()

    var utils = require('../../utils/utils.js');

    var Animation = require('../../utils/Animation.js');

    var Wheel = require('../../utils/Wheel.js');

    Page({

      /**

      * 页面的初始数据

      */

      data: {

        awardsList: {},

        list: [],

        statusBarHeight: getApp().globalData.statusBarHeight,

        scrollHeight: 200,

        windowWidth:0,

        windowHeight:0,

        awardsConfig: {

          count: 50,

          slicePrizes: [

            { text: "恭喜中大奖", img: "/assets/coupon_gold.png", title: "积分券x1", num: "1200", x: "1" },

            { text: "医疗服务费", img: "/assets/coupon_gold.png", title: "积分券x1", num: "50", x: "2" },

            { text: "健康保养费", img: "/assets/coupon_gold.png", title: "积分券x1", num: "500", x: "1" },

            { text: "谢谢参与", img: "/assets/coupon_gold.png", title: "积分券x3", num: "0", x: "2" },

            { text: "青春补偿费", img: "/assets/coupon_gold.png", title: "积分券x1", num: "200", x: "1" },

            { text: "感恩奉献费", img: "/assets/coupon_gold.png", title: "积分券x1", num: "100", x: "2" },

            { text: "咨询售后费", img: "/assets/coupon_gold.png", title: "积分券x1", num: "150", x: "1" },

            { text: "谢谢参与", img: "/assets/coupon_gold.png", title: "积分券x1", num: "0", x: "1" }, { text: "咨询售后费", img: "/assets/coupon_gold.png", title: "积分券x1", num: "150", x: "1" },

            { text: "谢谢参与", img: "/assets/coupon_gold.png", title: "积分券x1", num: "0", x: "1" }

          ],

        },

      },

      /**

      * 生命周期函数--监听页面加载

      */

      onLoad: function(options) {

        var that = this;

        var that = this;

        wx.getSystemInfo({

          success: function (res) {

            that.setData({

              windowWidth: res.windowWidth,

              windowHeight: res.windowHeight,

              scrollHeight: res.windowHeight - res.windowWidth / 750 * (getApp().globalData.statusBarHeight * 2 + 98)

            });

          },

        })

      },

      onReady: function(e) {

        let that = this,

          fps = 60, awardsConfig = that.data.awardsConfig,

            w = this.data.windowWidth / 750 * 600,

            h = this.data.windowWidth / 750 * 600,

            context = wx.createCanvasContext('canvas'),

            //定义canvas位置

            wheel = new Wheel(w / 2, w / 2, (w / 2) - 0, awardsConfig.slicePrizes),

            animation = new Animation(wheel, { w: w, h: h });

            wheel.prizeWidth = 30;

            wheel.prizeHeight = 30;

        // 更新动画

        let update = function () {

          // 清空

          context.clearRect(0, 0, w, h);

          // 画转盘

          wheel.draw(context);

          // 更新数据

          animation.draw(context);

          // 更新数据

          animation.update();

          // 绘图 

          context.draw()

        };

        setTimeout(update, 1000 / fps, 1000 / fps)

        wx.getSystemInfo({

          success: function(res) {

            that.setData({

              contentHeight: res.windowHeight

            });

          },

        })

        that.setData({

          count: awardsConfig.count

        })

        let len = awardsConfig.slicePrizes.length,

            rotateDeg = 360 / len / 2 ,

            list = [],

            turnNum = 1 / len;

        for (var i = 0; i < len; i++) {

          list.push({

            award: awardsConfig.slicePrizes[i].text,

          });

        };

        that.setData({

          list: list.concat(list)

        });

      },

      /**

      * 抽奖处理函数:

      */

      getLottery: function () {

        let that = this;

        // 获取奖品配置

        let awardsConfig = that.data.awardsConfig,

            runNum = 12, len = awardsConfig.slicePrizes.length,

            awardIndex = 0;

        awardIndex = parseInt(Math.random() * 6)

        console.log("奖品序号:" + awardIndex);

        // 旋转抽奖

        app.runDegs = app.runDegs || 0

        app.runDegs = app.runDegs + (360 - app.runDegs % 360) + (360 * runNum - awardIndex * (360 / len))

        //创建动画

        let animationRun = wx.createAnimation({

          duration: 4000,

          timingFunction: 'ease'

        })

        console.log(awardsConfig.slicePrizes[awardIndex]);

        that.animationRun = animationRun

        animationRun.rotate(app.runDegs - (360 / len * 2 + (360 / len)) ).step()

        that.setData({

          animationData: animationRun.export()

        })

      },

    })

    看完有问题 可以评论  觉得还可以的话点个赞  谢谢  相互交流

    相关文章

      网友评论

          本文标题:小程序 大转盘 抽奖 canvas animation

          本文链接:https://www.haomeiwen.com/subject/ikgoghtx.html