zoukankan      html  css  js  c++  java
  • 小程序 大转盘 抽奖 canvas animation

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

    两种方法及结合法

    一 通过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>
    //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 {
      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;
    }
    
    

    配合CSS3 扇形实现圆盘

    html

     <!-- 扇形 -->
                  <view class="canvas-list">
                    <view class="canvas-item2" wx:for="{{awardsConfig.slicePrizes}}" wx:key="key" style="transform: rotate({{item.item2Deg}});background-color:{{awardsConfig.slicePrizes.length==2?(index%2==0?'#faf5e7':'#f3e2c6'):''}};opacity:{{  awardsConfig.slicePrizes.length==2?item.opacity:  awardsConfig.slicePrizes.length==3?item.opacity:''}};{{size}}rpx;height:{{size/2-2}}rpx;transform-origin:{{size/2}}rpx {{size/2}}rpx">
                      <view class="canvas-item2-after" style="transform: rotate({{item.afterDeg}});background-color:{{index%2==0?'#faf5e7':'#f3e2c6'}};opacity:{{  awardsConfig.slicePrizes.length==3?'':item.opacity}};{{size/2}}rpx;height:{{size/2}}rpx;transform-origin: {{size/2}}rpx {{size/2}}rpx">
                      </view>
                      <view wx:if='{{awardsConfig.slicePrizes.length==3}}' class="canvas-item2-after" style="background-color:{{index%2==0?'#faf5e7':'#f3e2c6'}};{{size/2}}rpx;height:{{size/2}}rpx;transform-origin: {{size/2}}rpx {{size/2}}rpx"></view>
                    </view>
                  </view>
                  <!-- 选项内容 -->
                  <view class="wk-wheel-list">
                    <view class="wk-wheel-item" data-index="{{index}}" wx:for="{{awardsConfig.slicePrizes}}" wx:key='key'>
                      <view class="wk-wheel-icontent" style="height:262rpx;overflow:hidden;font-size:{{item.text.length>9?'20':'26'}}rpx;padding-top:5rpx;transform: rotate({{index*turnNum}}turn);transform-origin: 50% {{size/2-2}}rpx">
                        <view class="canvas-litem-text-name">{{item.text}}</view>
                        <view class="canvas-litem-text-image">
                          <image src="{{item.img}}" mode="widthFix" style="80rpx;max-height:60rpx;padding:10rpx 0 0;"></image>
                          <view class="canvas-litem-text-image-num">100</view>
                        </view>
                        <view style="font-size:20rpx;">{{item.num}}x1</view>
                      </view>
                    </view>
                  </view>
                </view>

    CSS

    /* //css扇形 */
    .canvas-item2 {
       position: absolute;
       left: 0px;
       top: 0;
       width: 620rpx;
       height: 328rpx;
       color: #e4370e;
       font-weight: bold;
       transform-origin: 330rpx 330rpx;
       overflow: hidden;
    }
     
    .canvas-item2-after {
       position: absolute;
       top: 0;
       left: 0;
       width: 330rpx;
       height: 330rpx;
       transform-origin: 330rpx 330rpx;
       opacity: 1;
    }
     
    .wk-wheel-list {
       position: absolute;
       left: 0;
       top: 0;
       width: 100%;
       height: 100%;
       z-index: 9;
    }
     
    .wk-wheel-item {
       position: absolute;
       left: 0;
       top: 0;
       width: 100%;
       height: 100%;
       color: #fff;
       text-shadow: 0 1px 1px rgba(255, 255, 255, 0.6);
    }
     
    .wk-wheel-icontent {
       position: relative;
       display: block;
       padding-top: 50rpx;
       margin: 0 auto;
       text-align: center;
       transform-origin: 50% 328rpx;
       color: #AA8B6B;
    }

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

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

    3.size 是圆盘的宽度

    设置点击抽奖按钮 两种方法 一直接在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>

    css

    .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

    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;
        that.initAdards()
        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,
            ;
       
        
        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)
        });
      },
    //初始化奖品数据 计算角度
      initAdards() {
        var that = this,
          awardsConfig = that.data.awardsConfig;
        var t = awardsConfig.slicePrizes.length; // 选项长度
        var e = 1 / t,
          i = 360 / t,
          r = i - 90;
    
        for (var g = 0; g < t; g++) {
          awardsConfig.slicePrizes[g].item2Deg = g * i + 90 - i / 2 + "deg"; //当前下标 * 360/长度 + 90 - 360/长度/2
          awardsConfig.slicePrizes[g].afterDeg = r + "deg";
          awardsConfig.slicePrizes[g].opacity = '1';
        }
        that.setData({
          turnNum: e, // 页面的单位是turn
          awardsConfig: awardsConfig,
        })
      },
      /**
      * 抽奖处理函数:
      */
      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).step()
        that.setData({
          animationData: animationRun.export()
        })
      },
    })
  • 相关阅读:
    lazyload【思路】
    图片旋转
    模拟滚动条【大体功能实现】
    Firefox window.close()的使用注意事项
    修改KindEditor的CSS文件
    ownerDocument property
    网易新闻图片展示效果
    关于td不支持position问题
    strcat strncat
    Tcl_FindExecutable
  • 原文地址:https://www.cnblogs.com/wukongz/p/13064866.html
Copyright © 2011-2022 走看看