精华内容
下载资源
问答
  • 微信小程序九宫格
    2021-06-10 06:18:29

    一、概述

    效果图

    二、实现

    定义数据源

    test.js

    Page({
    
      /**
       * 页面数据源
       */
      data: {
        iconColor: [
          'red', 'orange', 'yellow', 'green', 'rgb(0,255,255)', 'blue', 'purple'
        ],
        iconStyle: [
          {
            "type":"success",
            "size":30,
            "color":"#32CD32"
          },
          {
            "type": "success_no_circle",
            "size": 30,
            "color": "orange"
          },
          {
            "type": "info",
            "size": 30,
            "color": "yellow"
          },
          {
            "type": "warn",
            "size": 30,
            "color": "green"
          },
          {
            "type": "waiting",
            "size": 30,
            "color": "rgb(0,255,255)"
          },
          {
            "type": "cancel",
            "size": 30,
            "color": "blue"
          },
          {
            "type": "download",
            "size": 30,
            "color": "purple"
          },
          {
            "type": "search",
            "size": 30,
            "color": "#C4C4C4"
          },
          {
            "type": "clear",
            "size": 30,
            "color": "red"
          }
        ]
      }
    })
    
    View Code

    定义样式

    test.wxss

     /*
      九宫格容器布局样式
     */
     .grid-item-container {
      display: -webkit-flex;
      display: flex;
      align-items: center;
      justify-content: space-between;
      flex-wrap: wrap;
      border-top: 1rpx solid #D9D9D9;
    }
    
    /*
      item容器样式
    */
    .grid-item-child {
      display:flex;
      display: -webkit-flex;
      justify-content:center;
      flex-direction: column;
      flex-wrap: wrap;
      float: left;
      width: 33.33333333%;
      height: 200rpx;
      box-sizing: border-box;
      background-color: #FFFFFF;
      border-right: 1rpx solid #D9D9D9;
      border-bottom: 1rpx solid #D9D9D9;
    }
    
    /*
      icon样式
    */
    .grid-item-icon {
      display:flex;
      display: -webkit-flex;
      justify-content:center;
    }
    
    /*
     文本样式
    */
    .grid-item-label {
      display:flex;
      display: -webkit-flex;
      justify-content:center;
      color: #666;
      font-size: 14px;
    }
    
    View Code

    说明:

    使用 display: -webkit-flex;对布局做兼容。
    保证每排三个图标的两对对齐,采用:justify-content: space-between;属性。
    父元素必须设置 flex-wrap: wrap;属性进行换行,否则会在一排展示。
    每个子元素的宽度width: 33.33333333%;按照其占位大小分配。
    使用justify-content:center;属性设置元素居中。
    使用flex-direction: column;和flex-wrap: wrap;属性设置icon和text元素竖直排列。

    test.wxml

    <view class='grid-item-container'>
      <block wx:for="{{iconStyle}}" wx:key="index">
        <view class='grid-item-child'>
          <view>
            <icon class='grid-item-icon' type='{{item.type}}' size='{{item.size}}' color='{{item.color}}'/>
            <text class='grid-item-label'>{{item.type}}</text>
          </view>
        </view>
      </block>
    </view>
    
    View Code

    本文参考链接:

    https://blog.csdn.net/mjb00000/article/details/90513424

    更多相关内容
  • 微信小程序 九宫格 实现效果图: 小程序是长在微信上的,是移动端的界面,为了能够更方便的使用,我们常常希望使用九宫格界面的方式作为导航,那要如何实现呢? 基于一个简单的思考,九宫格就是三行三列,如果把行...
  • 微信小程序 九宫格抽奖demo 需要自己改些细节
  • jiugongge微信小程序九宫格抽奖效果图较卡顿真实效果是旋转的介绍地址:
  • 主要介绍了微信小程序项目实践之九宫格实现及item跳转功能,需要的朋友可以参考下
  • 主要为大家详细介绍了微信小程序实现九宫格抽奖,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 微信九宫格游戏小程序模板.zip微信小程序模板源码
  • 微信小程序九宫格图的排版----注意层次排版(层次最重要) 1.wxml中的代码(图片和数据都是网页获取来的,详细下看) 2.排版 3.使用.js文件进行事件加载 | | | |

    微信小程序九宫格图的排版----注意层次排版(层次最重要)

    在这里插入图片描述

    1.wxml中的代码(图片和数据都是网页获取来的,详细下看)
    在这里插入图片描述
    2.排版
    在这里插入图片描述
    在这里插入图片描述
    3.使用.js文件进行事件加载
    在这里插入图片描述

    |
    |

    在这里插入图片描述
    |
    |
    在这里插入图片描述

    展开全文
  • 微信小程序 九宫格 图片上传
  • 微信小程序九宫格抽奖和转盘抽奖的实现

    千次阅读 多人点赞 2021-05-07 20:05:36
    好了,下面是常见的两种抽奖方式:九宫格和转盘,在实际项目中用的还不错,分享给大家。 一、九宫格抽奖: 效果: 思路:    首先是结构上,用弹性布局就可以了,每一个奖品的宽度设置成3分之1,超

    描述:

    最近在工作中遇到了小程序抽奖的一些页面制作,以前制作网页抽奖的时候,在jQuery插件库谁便找一个Demo就可以满足我们的需求了,自己动手写的话不仅会拖慢项目进度,而且写出来的也未必有别人的那么流畅自然。而在小程序中我们就没有这么幸福了(ಥ﹏ಥ),并没有丰富的插件库供给我们使用,所以该写的还得自己动手写。好了,下面是常见的两种抽奖方式:九宫格和转盘,在实际项目中用的还不错,分享给大家。


    一、九宫格抽奖:

    效果:
    在这里插入图片描述

    思路:
       首先是结构上,用弹性布局就可以了,每一个奖品的宽度设置成3分之1,超出3个后让它换行;然后需要定义一个数组用来存放界面的奖品, 因为第五个内容是按钮,所以需要设置一个类型字段用来区分奖品和按钮。又因为需要一个旋转动画的效果,所以需要在奖品数组中设置一个是否已选中的状态字段。
       接着是逻辑上,因为旋转的轨迹是顺时针的,所以得出轨迹的执行顺序数组为:[0, 1, 2, 5, 8, 7, 6, 3],接着我们只需要循环这个数组,在里面设置一个定时器,让它能够在n秒后把第n个奖品的状态改为已选中,这样经过一个循环后,就可以实现动画旋转一圈的视觉效果了;可以旋转一圈后我们可以把这段代码先封装起来,接着我们只需要去循环这段代码,并且再套一个计时器,这样就可以实现旋转多圈的效果了。
       想法是完美的,但是实际项目中还存在很多的因素,比如说旋转每一圈中的衔接时间,调教旋转中的速度,让动画在最后一圈停留在对应的奖品上,这都是开发时要攻破的难关,具体还得认真观看下面代码。

    wxml:

    <view class="body">
      <view class="box">
        <block wx:for="{{prize_arr}}" wx:key="id">
          <!-- 判断是奖品还是抽奖按钮 -->
          <view wx:if="{{item.type=='btn'}}" bindtap="clickPrize" class="prize btn {{isTurnOver?'':'grayscale'}}">
            {{item.name}}
          </view>
          <view wx:else class="prize {{item.isSelected?'selected':''}}">{{item.name}}</view>
        </block>
      </view>
    </view>
    

    wxss:

    .body {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      width: 100vw;
      height: 100vh;
    }
    
    .box {
      display: flex;
      flex-wrap: wrap;
      width: 600rpx;
    }
    
    .box .prize {
      width: 200rpx;
      height: 200rpx;
      line-height: 200rpx;
      text-align: center;
      font-size: 40rpx;
      font-weight: 700;
      color: white;
      background-color: orange;
      border: 2px solid snow;
      box-sizing: border-box;
    }
    
    .box .btn {
      color: tomato;
      background-color: gold;
    }
    
    .box .selected {
      background-color: orangered;
    }
    
    .grayscale {
      filter: grayscale(50%);
    }
    

    js:

    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        prize_arr: [
          {id: '1',type: 'prize',name: '奖品1',isSelected: false},
          {id: '2',type: 'prize',name: '奖品2',isSelected: false},
          {id: '3',type: 'prize',name: '奖品3',isSelected: false},
          {id: '4',type: 'prize',name: '奖品8',isSelected: false},
          {id: '5',type: 'btn',name: '按钮',isSelected: false},
          {id: '6',type: 'prize',name: '奖品4',isSelected: false},
          {id: '7',type: 'prize',name: '奖品7',isSelected: false},
          {id: '8',type: 'prize',name: '奖品6',isSelected: false},
          {id: '9',type: 'prize',name: '奖品5',isSelected: false},
        ],
        // 抽奖状态,是否转完了
        isTurnOver: true
      },
    
      // 点击抽奖
      clickPrize() {
        // 如果不在抽奖状态中,则执行抽奖旋转动画
        if (this.data.isTurnOver) {
          // 把抽奖状态改为未完成
          this.setData({
            isTurnOver: false
          })
          // 这里开始假设已经调取后端接口拿到抽奖后返回的ID
          let prize_id = 7;
          // 调用抽奖方法
          this.lottery(prize_id);
        } else {
          wx.showToast({
            title: '请勿重复点击',
            icon: 'none'
          })
        }
      },
    
      // 抽奖旋转动画方法
      lottery(prize_id) {
        console.log('中奖ID:' + prize_id)
        /*
         * 数组的长度就是最多所转的圈数,最后一圈会转到中奖后的位置
         * 数组里面的数字表示从一个奖品跳到另一个奖品所需要的时间
         * 数字越小速度越快
         * 想要修改圈数和速度的,更改数组个数和大小即可
         */
        let num_interval_arr = [90, 80, 70, 60, 50, 50, 50, 100, 150, 250];
        // 旋转的总次数
        let sum_rotate = num_interval_arr.length;
        // 每一圈所需要的时间
        let interval = 0;
        num_interval_arr.forEach((delay, index) => {
          setTimeout(() => {
            this.rotateCircle(delay, index + 1, sum_rotate, prize_id);
          }, interval)
          //因为每一圈转完所用的时间是不一样的,所以要做一个叠加操作
          interval += delay * 8;
        })
      },
    
      /*
       * 封装旋转一圈的动画函数,最后一圈可能不满一圈
       * delay:表示一个奖品跳到另一个奖品所需要的时间
       * index:表示执行到第几圈
       * sum_rotate:表示旋转的总圈数
       * prize_id:中奖后的id号
       */
      rotateCircle(delay, index, sum_rotate, prize_id) {
        // console.log(index)
        let _this = this;
        /*
         * 页面中奖项的实际数组下标
         * 0  1  2
         * 3     5
         * 6  7  8
         * 所以得出转圈的执行顺序数组为 ↓
         */
        let order_arr = [0, 1, 2, 5, 8, 7, 6, 3];
        // 页面奖品总数组
        let prize_arr = this.data.prize_arr;
        // 如果转到最后以前,把数组截取到奖品项的位置
        if (index == sum_rotate) {
          order_arr.splice(prize_id)
        }
        for (let i = 0; i < order_arr.length; i++) {
          setTimeout(() => {
            // 清理掉选中的状态
            prize_arr.forEach(e => {
              e.isSelected = false
            })
            // 执行到第几个就改变它的选中状态
            prize_arr[order_arr[i]].isSelected = true;
            // 更新状态
            _this.setData({
              prize_arr: prize_arr
            })
            // 如果转到最后一圈且转完了,把抽奖状态改为已经转完了
            if (index == sum_rotate && i == order_arr.length - 1) {
              _this.setData({
                isTurnOver: true
              })
            }
          }, delay * i)
        }
      }
    
    })
    
    

    衔接版js: 非第一次转时,会把上一次未跳完的格子转完,逻辑就是点击抽奖时做个标记来判断是否需要把没跳完的格子跳完。

    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        prize_arr: [
          {id: '1',type: 'prize',name: '奖品1',isSelected: false},
          {id: '2',type: 'prize',name: '奖品2',isSelected: false},
          {id: '3',type: 'prize',name: '奖品3',isSelected: false},
          {id: '4',type: 'prize',name: '奖品8',isSelected: false},
          {id: '5',type: 'btn',name: '按钮',isSelected: false},
          {id: '6',type: 'prize',name: '奖品4',isSelected: false},
          {id: '7',type: 'prize',name: '奖品7',isSelected: false},
          {id: '8',type: 'prize',name: '奖品6',isSelected: false},
          {id: '9',type: 'prize',name: '奖品5',isSelected: false},
        ],
        /*
         * 数组的长度就是最多所转的圈数,最后一圈会转到中奖后的位置
         * 数组里面的数字表示从一个奖品跳到另一个奖品所需要的时间
         * 数字越小速度越快
         * 想要修改圈数和速度的,更改数组个数和大小即可
         */
        num_interval_arr: [90, 80, 70, 60, 50, 50, 50, 100, 150, 250],
        // num_interval_arr: [90, 80],
        /*
         * 页面中奖项的实际数组下标
         * 0  1  2
         * 3     5
         * 6  7  8
         * 所以得出转圈的执行顺序数组为 ↓
         */
        order_arr: [0, 1, 2, 5, 8, 7, 6, 3],
        // 抽奖状态,是否转完了
        isTurnOver: true,
        // 是否需要复原,把没转完的圈转完
        isRecover: false,
        // 记录上一次抽奖后的奖品id
        prize_id_last: ''
      },
    
      // 点击抽奖
      clickPrize() {
        // 如果不在抽奖状态中,则执行抽奖旋转动画
        if (this.data.isTurnOver) {
          // 把抽奖状态改为未完成
          this.setData({
            isTurnOver: false
          })
          // 这里开始假设已经调取后端接口拿到抽奖后返回的ID
          let prize_id = 7;
          // 调用抽奖方法
          this.lottery(prize_id);
        } else {
          wx.showToast({
            title: '请勿重复点击',
            icon: 'none'
          })
        }
      },
    
      // 抽奖旋转动画方法
      async lottery(prize_id) {
        console.log('中奖ID:' + prize_id)
        // 如果不是第一次抽奖,需要等待上一圈没跑完的次数跑完再执行
        this.recover().then(() => {
          let num_interval_arr = this.data.num_interval_arr;
          let order_arr = this.data.order_arr;
          // 旋转的总次数
          let sum_rotate = num_interval_arr.length;
          // 每一圈所需要的时间
          let interval = 0;
          num_interval_arr.forEach((delay, index) => {
            setTimeout(() => {
              this.rotateCircle(delay, index + 1, sum_rotate, prize_id, order_arr);
            }, interval)
            //因为每一圈转完所用的时间是不一样的,所以要做一个叠加操作
            interval += delay * 8;
          })
        })
      },
    
      /*
       * 封装旋转一圈的动画函数,最后一圈可能不满一圈
       * delay:表示一个奖品跳到另一个奖品所需要的时间
       * index:表示执行到第几圈
       * sum_rotate:表示旋转的总圈数
       * prize_id:中奖后的id号
       * order_arr_pre:表示旋转这一圈的执行顺序
       */
      rotateCircle(delay, index, sum_rotate, prize_id, order_arr_pre) {
        // console.log(index)
        let _this = this;
        // 页面奖品总数组
        let prize_arr = this.data.prize_arr;
        // 执行顺序数组
        let order_arr = []
        // 如果转到最后以前,把数组截取到奖品项的位置
        if (index == sum_rotate) {
          order_arr = order_arr_pre.slice(0, prize_id)
        } else {
          order_arr = order_arr_pre;
        }
        for (let i = 0; i < order_arr.length; i++) {
          setTimeout(() => {
            // 清理掉选中的转态
            prize_arr.forEach(e => {
              e.isSelected = false
            })
            // 执行到第几个就改变它的选中状态
            prize_arr[order_arr[i]].isSelected = true;
            // 更新状态
            _this.setData({
              prize_arr: prize_arr
            })
            // 如果转到最后一圈且转完了,并且是非重置圈,把抽奖状态改为已经转完了
            if (index === sum_rotate && i === order_arr.length - 1 && !this.data.isRecover) {
              _this.setData({
                isTurnOver: true,
                isRecover: true,
                prize_id_last: prize_id
              })
            }
          }, delay * i)
        }
      },
    
      // 复原,把上一次抽奖没跑完的次数跑完
      async recover() {
        if (this.data.isRecover) { // 判断是否需要重置操作
          let delay = this.data.num_interval_arr[0]; // 为了衔接流程,使用第一圈的转速
          // console.log(delay)
          let order_arr = this.data.order_arr;
          // console.log(order_arr)
          let prize_id_last = this.data.prize_id_last; // 上一次抽奖的id
          // console.log(prize_id_last)
          order_arr = order_arr.slice(prize_id_last); // 截取未跑完的格子数组
          // console.log(order_arr)
          return await new Promise(resolve => { // 确保跑完后才去执行新的抽奖
            this.rotateCircle(delay, 1, 1, 8, order_arr); // 第一圈的速度,最多只有一圈,旋转一圈,跑到最后一个奖品为止,未跑完的数组
            setTimeout(() => { // 确保跑完后才告诉程序不用重置复原了
              this.setData({
                isRecover: false,
              })
              resolve() // 告诉程序Promise执行完了
            }, delay * order_arr.length)
          })
        }
      }
    
    })
    

    二、转盘抽奖:

    效果:
    在这里插入图片描述
    思路:
       首先是结构上,我们从设计那拿到psd后,把转盘背景和指针按钮分离成两张图片就好,接着用弹性布局或悬浮布局定一下位置就好。
       接着是逻辑上,我的第一想法使用css3的animation+transform:rotate()来制作,但是想了一下要动态设置旋转的角度,小程序也不好操作dom,所以直接使用官方提供的Animation API来制作了。需要注意一下我这转盘是有6个奖项,所以一个奖项的度数为:60,根据自己的项目,换算一下就好了;另外需要注意的是小程序是否要执行动画是看当前状态和要执行的实例数据间是否存在差值,换句话说就是如果我第一次抽到3等奖,我第二次又是抽中了3等奖,旋转的度数没有变,那么小程序会判断为当前不存在差值,所以会偷懒,直接不转了,具体解决方案看代码。

    wxml:

    <view class="body">
      <view class="box">
        <image class="bg" src="{{bg}}" animation="{{animationRotate}}"></image>
        <image bindtap="lottery" class="arrows {{isTurnOver?'':'grayscale'}}" src="{{arrows}}"></image>
      </view>
    </view>
    

    wxss:

    .body {
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      width: 100vw;
      height: 100vh;
    }
    
    .box {
      position: relative;
      display: flex;
      justify-content: center;
      align-items: center;
      width: 600rpx;
      height: 600rpx;
    }
    
    .box .bg {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
    
    .box .arrows {
      position: relative;
      top: -28rpx;
      width: 200rpx;
      height: 249rpx;
    }
    
    .grayscale {
      filter: grayscale(70%);
    }
    

    js:

    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        // 转盘奖品背景
        bg: "http://r.photo.store.qq.com/psc?/V14ZaBeY40XWC8/45NBuzDIW489QBoVep5mcT0Lq.gBxwEb6.hf44ibdoBF*Yne9.pzFu6WW1t*k2C7iFgwK3jc0jMvFefvW0IfraslW4FNcfHPYyIdFLecyJ0!/r",
        // 转盘箭头抽奖按钮
        arrows: "http://r.photo.store.qq.com/psc?/V14ZaBeY40XWC8/45NBuzDIW489QBoVep5mcT0Lq.gBxwEb6.hf44ibdoA2KiCwrHNJS*10VP4yg3bnkt2TA7zugdvTHvyHaWr2uplgBObbdubFayYw6e*PbW0!/r",
        // 抽奖状态,是否转完了
        isTurnOver: true
      },
    
      // 点击抽奖按钮
      lottery() {
        // 如果不在抽奖状态中,则执行抽奖旋转动画
        if (this.data.isTurnOver) {
          // 把抽奖状态改为未完成
          this.setData({
            isTurnOver: false
          })
          // 这里开始假设已经调取后端接口拿到抽奖后返回的ID
          let prize_id = 3;
          // 调用旋转动画方法
          this.rotate(prize_id)
        } else {
          wx.showToast({
            title: '请勿重复点击',
            icon: 'none'
          })
        }
      },
    
      // 旋转动画方法
      rotate(prize_id) {
        // 执行完动画所需要的时间
        let _duration = 10000;
        let animationRotate = wx.createAnimation({
          duration: _duration,
          timingFunction: 'ease', //动画以低速开始,然后加快,在结束前变慢
        })
        // 解决二次点击抽奖后不再旋转的问题
        animationRotate.rotate(0).step({
          duration: 1
        })
        /*
         * 旋转的角度
         * 这转盘有6个奖项,所以一个奖项的度数为:360除以6等于60、
         * 要转完一圈 → 60 * 6
         * 为了让动画看起来舒服我设置了20圈 → 60 * 6 * 20
         * 又因为转盘是顺时针旋转的,默认指定奖品1
         * 所以需要减去 → 60 * (prize_id - 1) 方可在最后一圈转到对应的位置
         * 可以根据自己的设计稿奖品的个数进行调整
         * */
        let angle = (60 * 6 * 20) - 60 * (prize_id - 1);
        animationRotate.rotate(angle).step()
        this.setData({
          animationRotate: animationRotate.export()
        })
        // 设置倒计时,保证最后一圈执行完了,才更改状态
        setTimeout(() => {
          this.setData({
            isTurnOver: true
          })
        }, _duration)
      }
    
    })
    

    衔接版js: 会在原来的角度上继续旋转,逻辑就是让角度无线放大,比如第一次抽奖圈转了20圈,那么第二次点击就会转到40圈的位置,实际也是转了20圈上下,因为程序偷懒,跑过的20圈并不会再跑了。

    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        // 转盘奖品背景
        bg: "http://r.photo.store.qq.com/psc?/V14ZaBeY40XWC8/45NBuzDIW489QBoVep5mcT0Lq.gBxwEb6.hf44ibdoBF*Yne9.pzFu6WW1t*k2C7iFgwK3jc0jMvFefvW0IfraslW4FNcfHPYyIdFLecyJ0!/r",
        // 转盘箭头抽奖按钮
        arrows: "http://r.photo.store.qq.com/psc?/V14ZaBeY40XWC8/45NBuzDIW489QBoVep5mcT0Lq.gBxwEb6.hf44ibdoA2KiCwrHNJS*10VP4yg3bnkt2TA7zugdvTHvyHaWr2uplgBObbdubFayYw6e*PbW0!/r",
        // 抽奖状态,是否转完了
        isTurnOver: true,
        // 转的总圈数,最后一圈可能不满
        num_total: 20
      },
    
      // 点击抽奖按钮
      lottery() {
        // 如果不在抽奖状态中,则执行抽奖旋转动画
        if (this.data.isTurnOver) {
          // 把抽奖状态改为未完成
          this.setData({
            isTurnOver: false
          })
          // 这里开始假设已经调取后端接口拿到抽奖后返回的ID
          let prize_id = 3;
          // 调用旋转动画方法
          this.rotate(prize_id)
        } else {
          wx.showToast({
            title: '请勿重复点击',
            icon: 'none'
          })
        }
      },
    
      // 旋转动画方法
      rotate(prize_id) {
        // 执行完动画所需要的时间
        let _duration = 10000;
        let animationRotate = wx.createAnimation({
          duration: _duration,
          timingFunction: 'ease', //动画以低速开始,然后加快,在结束前变慢
        })
        /*
         * 旋转的角度
         * 这转盘有6个奖项,所以一个奖项的度数为:360除以6等于60、
         * 要转完一圈 → 60 * 6
         * 为了让动画看起来舒服我设置了20圈 → 60 * 6 * 20
         * 又因为需要连贯抽取非第一次,所以二次抽奖时会在原来的圈数上自加,
         * 也就成了60 * 6 * num_total,num_total每转完一次都会叠加上自身
         * 又因为转盘是顺时针旋转的,默认指定奖品1
         * 所以需要减去 → 60 * (prize_id - 1) 方可在最后一圈转到对应的位置
         * 可以根据自己的设计稿奖品的个数进行调整
         * */
        let num_total = this.data.num_total;
        let angle = (60 * 6 * num_total) - 60 * (prize_id - 1);
        animationRotate.rotate(angle).step()
        this.setData({
          animationRotate: animationRotate.export()
        })
        // 设置倒计时,保证最后一圈执行完了,才更改状态
        setTimeout(() => {
          this.setData({
            isTurnOver: true,
            num_total: num_total + num_total
          })
        }, _duration)
      }
    
    })
    

    素材:


    附加题:

    概率: 虽然概率这块是放在后端处理,但是它的大概原理是怎么样的呢?接下来我会以我司的抽奖后台方式来和大家探讨。从下面的图中可以看到,每一项奖品都会有一个ID、名称,另外除了奖品数量外还有奖品概率,这就意味着奖品的概率并不一定是按照总数占比来的,并且可以看到红字,一般总概率是要为100(即100%,我猜这样做的目的是为了防止有小数点的情况造成比例不精准)。
    在这里插入图片描述

    ▲抽奖方式可能会有出入的地方:
      1.我司的抽奖方式是这样的,它并不一定是只抽一下的,会按概率的级别依次抽取,每个奖品都会抽一次,比如说先以奖品一的抽奖概率去抽奖品一,如果没有抽中,那么就会去用奖品二的概率抽取奖品二,如果奖品二没有抽中继续往后,如果所有奖品抽过一次都没中,那返回未中提示;
      2.另外,比如我抽到了一等奖,但是一等奖被抽光了,那么此时它会直接向下取去拿奖品二,如果奖品二也没有,会一直往后取。大概意思是我抽中一等奖了,抽完了没有货,那么就有资格直接拿后面级别的奖品,而非重新去抽取。

    下面是我通过制作一些抽奖活动后,自个理解后写的抽奖概率代码,当然并不是说后端的代码就是这样,毕竟后端不止一门语言,而且还会涉及到数据库操作,我这代码仅供大家参考参考,提升提升思维而已。(未抽中和谢谢惠顾的意思是一样的)

    /*
     * 奖品数组
     * num: 该奖品剩余数量
     * probability:  该奖品抽中概率
     */
    let prizeArr = [
    		{id: '0',name: '一等奖',num: 1,probability: 10}, 
    		{id: '1',name: '二等奖',num: 2,probability: 20}, 
    		{id: '2',name: '三等奖',num: 3,probability: 30}, 
    		{id: '3',name: '谢谢惠顾',num: 99999,probability: 40}
    	];
    
    // 定义数组对象排序函数
    function compare(property) {
        return function(a, b) {
            let value1 = a[property];
            let value2 = b[property];
            return value1 - value2; //降序为value2 - value1
        }
    }
    
    // 根据奖品的概率重新排序,因为后续如果抽中靠前的奖品,并且该奖抽完了,会直接向下取奖品
    prizeArr.sort(compare('probability'))
    
    // 得到一个两数之间的随机数
    function getRandomArbitrary(min, max) {
        return Math.random() * (max - min) + min;
    }
    
    // 点击抽奖
    function clickLottery() {
        let sum = prizeArr.reduce((prev, cur) => prev + cur.num, 0); // 剩余奖品的总数
        // console.log(sum)  
        let totalProbability = prizeArr.reduce((prev, cur) => prev + cur.probability, 0); // 全部奖品的总概率
        // console.log(totalProbability)
        if (sum <= 0) {
            console.log("奖品已经抽完了!")
            return
        }
        try {
            prizeArr.forEach((e, index) => {
                let probability = e.probability; // 当前奖品的概率
                // console.log(probability)
                let random_num = getRandomArbitrary(0, totalProbability); // 0到总概率的随机数
                // console.log(random_num)
                if (random_num <= probability) { // 如果随机数小于等于抽奖概率,说明抽中了该项奖品
                    // console.log(e.num)
                    if (e.num > 0) { // 如果当前奖品还有余量,返回改奖项
                        e.num -= 1; // 相应的奖品数减一
                        throw Error(e.name)
                    } else { // 否则无需再抽,直接向下取奖品
                        if (index + 1 < prizeArr.length) { // 如果抽中的不是最后一个奖品,数组未越界
                            for (let i = index + 1; i <= prizeArr.length; i++) {
                                console.log(i)
                                if (prizeArr[i].num > 0) { // 如果后面的奖品还有余量,返回该奖项
                                    prizeArr[i].num -= 1; // 相应的奖品数减一
                                    throw Error(prizeArr[i].name)
                                }
                            }
                        }
                    }
                }
            })
        } catch (e) {
            console.log(e.message)
            return
        }
        console.log("很遗憾未抽中!")
    }
    // 触发抽奖
    clickLottery();
    // console.log(prizeArr)
    

    在这里插入图片描述

    展开全文
  • 微信小程序九宫格布局

    千次阅读 2020-10-05 20:21:14
    true, name: '微信', url: '', icon: '/imgs/wechat.png', code: '11' }, { isBind: true, name: '火车票', url: '', icon: '/imgs/tick.png', code: '11' }, ] }, { title: '家庭', items: [{ isBind: true, name: ...

    先上效果图

    image.png

    使用注意事项

    1:注意在app.json中注册页面路径

    2:如果要增加新的Item,可到js中对listService数组进行增加

    3:listService参数[
    title:分类标题
    items:这个分类下的所有Item[
    name:这个Item的名字
    url:这个Item点击跳转路径
    icon:图标
    ]
    ]

    WXML代码

    
    <view id='services' class='services'>
      <view class="grid" wx:for="{{servers}}" wx:key="">
        <view class='grid-title'>
          <text>{{item.title}}</text>
        </view>
        <view class='grid-items'>
          <block wx:for="{{item.items}}" wx:key="">
            <view class='grid-item'>
              <view wx:if="{{item.enabled}}" class='mask'>
                <text>{{item.detail}}</text>
              </view>
              <view class='navigator' data-path='{{item.url}}' data-isBind='{{item.isBind}}' bindtap='bindNavigator'  hover-class="none">
                <view class='item-content'>
                  <view class="item-content-icon">
                    <image src="{{item.icon}}" mode="scaleToFill" />
                  </view>
                  <text class="weui-grid_label">{{item.name}}</text>
                </view>
              </view>
            </view>
          </block>
        </view>
      </view>
    </view>
    

    WXSS

    page{
      background:#eeecec;
    }
    .enable{
      z-index: 99999;
      background: #404040;
      opacity: 0.8;
      position: absolute;
      width: 100;
      bottom: 0px;
      top: 0px;
      left: 0px;
      right: 0px;
      display: flex;
      justify-content: center;
      align-items: center;
      color: #ffffff;
    }
    .enable text{
      color: #fafafa;
      font-size: 18px;
      font-weight: bold;
    
    }
    
    
    .grid {
      background: #ffffff;
      margin-bottom:10px;
    }
    .services{
      background:#f5f5f5;
    
    }
    .navigator{
    padding:20px 10px;
    }
    .grid-items {
      
      position: relative;
      overflow: hidden;
      display: flex;
      flex-direction: row;
      flex-wrap: wrap;
    
    }
    .grid-items::before{
        content: " ";
        position: absolute;
        left: 0;
        top: 0;
        right: 0;
        height: 1px;
        border-top: 1px solid #d9d9d9;
    }
    .grid-items::after{
        content: "";
        position: absolute;
        left: 0;
        top: 0;
        width: 1px;
        bottom: 0;
        border-left: 1px solid #d9d9d9;
        color: #d9d9d9;
        -webkit-transform-origin: 0 0;
        transform-origin: 0 0;
        -webkit-transform: scaleX(0.5);
        transform: scaleX(0.5);
    }
    .grid-item{
        position: relative;
        float: left;
        width: 33.33333333%;
        box-sizing: border-box;
    }
    
    .grid-item::before{
       content: " ";
        position: absolute;
        right: 0;
        top: 0;
        width: 1px;
        bottom: 0;
        border-right: 1px solid #d9d9d9;
        color: #d9d9d9;
        -webkit-transform-origin: 100% 0;
        transform-origin: 100% 0;
        -webkit-transform: scaleX(0.5);
        transform: scaleX(0.5);
    }
    .grid-item::after{
        content: " ";
        position: absolute;
        left: 0;
        bottom: 0;
        right: 0;
        height: 1px;
        border-bottom: 1px solid #d9d9d9;
        color: #d9d9d9;
        -webkit-transform-origin: 0 100%;
        transform-origin: 0 100%;
        -webkit-transform: scaleY(0.5);
        transform: scaleY(0.5);
    }
    .item-content{
        position: relative;
    
        padding: 0px 0px;
        width: 100%;
        box-sizing: border-box;
    }
    .item-content-icon{
         width: 32px;
        height: 32px;
        margin: 0 auto;
    }
    .item-content-icon image{
        display: block;
        width: 100%;
        height: 100%;
    }
    .weui-grid_label {
        display: block;
        text-align: center;
        font-weight: bold;
        color: #707070;
        font-size: 16px;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
    }
    .grid-title{
        display: block;
      
        font-weight: bold;
        color: #707070;
        font-size: 14px;
        white-space: nowrap;
        text-overflow: ellipsis;
        overflow: hidden;
        padding: 7px;
    
    }
    .mask{
      width: 100%;
      height: 100%;
    
      position: absolute;
      z-index: 999;
      text-align: center;
      background: rgba(0, 0, 0, 0.619);
      color: #eee8e8;
      line-height: 32px;
      display: flex;
    
    }
    

    最重要的JS

    
    const app = getApp()
    
    Page({
      data: {
        servers:[]
      },
    
      onLoad: function () {
        var listService = [
          {
            title: '社会',
            items: [{
              name: '捐助',
              url: '/pages/TestPage/TestPage',
              icon: '/imgs/love.png',
              code: '11'
            },
            {
              isBind: true,
              name: '捐衣物',
              url: '',
              icon: '/imgs/clothes.png',
              code: '11'
            }
            ]
          },
    
          {
            title: '生活',
            items: [{
              name: '微信',
              url: '',
              icon: '/imgs/wechat.png',
              code: '11'
            },
            {
              isBind: true,
              name: '微信',
              url: '',
              icon: '/imgs/wechat.png',
              code: '11'
            }, {
              isBind: true,
              name: '火车票',
              url: '',
              icon: '/imgs/tick.png',
              code: '11'
            },
            ]
          },
          {
            title: '家庭',
            items: [{
              isBind: true,
              name: '账单',
              url: '',
              icon: '/imgs/bill.png',
              code: '11'
            }
            ]
          }, {
            title: '其他服务',
            items: []
          }
        ]
        this.setData({
          servers: listService
        })
      },
    
      /**
       * 当点击Item的时候传递过来
       */
      bindNavigator: function (e) {
        wx.navigateTo({
          url: e.currentTarget.dataset.path,
        })
    
      },
    })
    
    
    展开全文
  • 抽奖大转盘是个很百搭的应用,各种大小app都喜欢挂上这么个东西嗨皮一下。核心功能就是一个概率算法,再结合应用场景做的一些调整。 今天介绍一下《爱豆UP榜》的
  • 因公司需求要做一个小程序九宫格抽奖,但是一块又没有合适的插件,于是到网上看到一个,还挺不错的。 效果图 1.外面一圈闪烁的小球是用js控制的样式.500ms改变一次样式.简单粗暴; 2.抽奖的item也是js控制背景,...
  • js faceList:[ { "lximage": "../../images/l_xin.png", "id": 0 }, { "lximage": "../../images/l_fang.png", "id": 1 }, { "lximage": ...
  • let timer;let onDrawing = false; // 是否可进行抽奖标识,默认为false可进行抽奖let drawIndex = 0; //抽奖过程KEYComponent({/*** 组件的属性列表*/properties: {},/*** 关闭组件样式隔离*/options: {...
  • gallery.gif数据:依赖接口wx.upload、chooseImage与preview数据请求通过LeanCloud完成图片选择:https://mp.weixin.qq.com/debug/wxadoc/dev/api/media-picture.html#wxchooseimageobject前端处理:1....
  • 微信小程序-九宫格gridView封装实现
  • 微信小程序九宫格预览+单张图片预览
  • 微信小程序九宫格

    2021-10-08 22:07:36
    微信小程序九宫格 不用定死父容器的宽高,实现自适应九宫格 wxml <view class="moreimg"> <block wx:for="{{9}}" wx:key="index"> <view class="moreimg-wrap"> <image class="moreimg...
  • 1.实现效果 2.代码 码云链接: link.
  • 小程序版的九宫格数独游戏

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,148
精华内容 859
关键字:

微信小程序九宫格