微信小程序——抽奖之九宫格

 

 

<view class="container">
  <view class="zhuanpan_box_out">
    <image class="zhunapan_bg" src="https://s1.ax1x.com/2023/06/14/pCuPMrT.png" mode="aspectFill"></image>
    <view class="circle" wx:for="{{circleList}}" wx:key="index" style="top:{{item.topCircle}}rpx;left:{{item.leftCircle}}rpx;background-color: {{(index%2==0)?colorCircleFirst:colorCircleSecond}};"></view>
    <view class="zhuanpan_box_in">
      <view class="content-out" wx:for="{{awardList}}" wx:key="index" style="top:{{item.topAward}}rpx;left:{{item.leftAward}}rpx;background: {{item.isSelected?colorAwardSelect:colorAwardDefault}};">
        <view class="award-text">{{item.awardText}}</view>
      </view>
      <view class="draw_btn" bindtap="startGame">
        <image class="draw_btn_bg" src="https://s1.ax1x.com/2023/06/14/pCuPRQP.png" mode="aspectFill"></image>
      </view>
    </view>
  </view>
</view>
.container {
  width: 100vw;
  height: 100vh;
  background: url('https://s1.ax1x.com/2023/06/14/pCuPAaQ.png') no-repeat center top;
  background-size: 750rpx 1624rpx;
}

.zhuanpan_box_out {
  width: 750rpx;
  height: 732rpx;
  /* 水平垂直居中 */
  margin: auto auto;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

.zhuanpan_box_out .zhunapan_bg {
  display: block;
  width: 750rpx;
  height: 732rpx;
}

.zhuanpan_box_in .draw_btn {
  width: 166rpx;
  height: 150rpx;
  position: absolute;
  top: 346rpx;
  left: 294rpx;
}

.zhuanpan_box_in .draw_btn .draw_btn_bg {
  width: 100%;
  height: 100%;
  position: absolute;
}

.zhuanpan_box_in .draw_btn .draw_btn_text {
  position: absolute;
  left: 43rpx;
  top: 80rpx;
  width: 80rpx;
  font-size: 20rpx;
  font-family: PingFangSC-Medium, PingFang SC;
  font-weight: 500;
  color: #B16042;
  text-align: center;
}

/**小圆球*/
.circle {
  position: absolute;
  display: block;
  border-radius: 50%;
  height: 18rpx;
  width: 18rpx;
}

/* 奖品的容器 */
.content-out {
  position: absolute;
  width: 166rpx;
  height: 150rpx;
  background-color: #f5f0fc;
  border-radius: 10rpx;
  /* box-shadow: 0 5px 0 #d87fde; */
}

/*奖品的文案 */
.content-out .award-text {
  width: 100%;
  height: 100%;
  color: #3c3c3c;
  font-weight: 500;
  font-size: 32rpx;
  display: flex;
  justify-content: center;
  align-items: center;
}

1. 需要通过接口去获取奖品列表 (awardList)

2.绘制灯 实现闪烁的效果

3.设置奖品 的位置与设置圆点位置的原理一样  奖品可以用图片代替(根据需求来设置)

4.点击抽奖按钮时  判断抽奖状态,如果不在抽奖状态中,则执行抽奖旋转动画

5.调用接口获取奖品的id (可以设置必中某个奖品)

Page({
  data: {
    circleList: [], //圆点数组
    colorCircleFirst: '#F8AC4C', //圆点颜色1
    colorCircleSecond: '#FBF8D7', //圆点颜色2
    colorAwardDefault: 'linear-gradient(180deg, #EFD98D 0%, #FAECBF 9%, #FAECBF 91%, #E7C86C 100%) ', //奖品默认颜色
    colorAwardSelect: '#ffe400', //奖品选中颜色
    indexSelect: '', //被选中的奖品index
    //奖品数组
    awardList: [{
      awardId: 1,
      awardText: "英语1"
    }, {
      awardId: 2,
      awardText: "英语2"
    }, {
      awardId: 3,
      awardText: "英语3"
    }, {
      awardId: 4,
      awardText: "英语4"
    }, {
      awardId: 5,
      awardText: "英语5"
    }, {
      awardId: 6,
      awardText: "英语6"
    }, {
      awardId: 7,
      awardText: "英语7"
    }, {
      awardId: 8,
      awardText: "英语8"
    }],
    //抽中的奖品信息
    prizeInfo: [],
    num_interval_arr: [90, 80, 70, 60, 50, 50, 50, 100, 150, 250],
    //所以得出转圈的执行顺序数组为 
    order_arr: [0, 1, 2, 5, 8, 7, 6, 3],
    // 抽奖状态,是否转完了
    isTurnOver: true,
    // 是否需要复原,把没转完的圈转完
    isRecover: false,
    // 记录上一次抽奖后的奖品位置
    awardSort_last: '',
    prize_id: '', //奖品id
  },
  onShow() {
    this.drawTheLamp()
    this.setAwardList()
  },


  //绘制灯
  drawTheLamp() {
    let _this = this;
    //设置圆点相对于左上角定位点的距离
    let topCircle = 0; //距离顶部
    let leftCircle = 0; //距离左边
    let circleList = []; //创建圆点数据对象
    // 创建圆点的位置顺序是 左上————右上————右下————左下————右上
    for (let i = 0; i < 32; i++) {
      if (i == 0) { //左上角圆点
        topCircle = 162;
        leftCircle = 146;
      } else if (i < 8) {
        topCircle = 162;
        leftCircle = leftCircle + 64;
      } else if (i == 8) { //右上角圆点
        topCircle = 190;
        leftCircle = 641;
      } else if (i < 16) {
        topCircle = topCircle + 64;
        leftCircle = 641;
      } else if (i == 16) { //右下角圆点
        topCircle = 678;
        leftCircle = 595;
      } else if (i < 24) {
        topCircle = 678;
        leftCircle = leftCircle - 64;
      } else if (i == 24) { //左下角圆点
        topCircle = 640;
        leftCircle = 94;
      } else if (i < 32) {
        topCircle = topCircle - 63;
        leftCircle = 94;
      } else {
        return
      }
      // 添加圆点对象
      circleList.push({
        topCircle: topCircle,
        leftCircle: leftCircle
      });
    }
    this.setData({
      circleList
    })
    //圆点闪烁   每500毫秒改变交换圆点的颜色
    setInterval(function () {
      if (_this.data.colorCircleFirst == '#F8AC4C') {
        _this.setData({
          colorCircleFirst: '#FBF8D7',
          colorCircleSecond: '#F8AC4C',
        })
      } else {
        _this.setData({
          colorCircleFirst: '#F8AC4C',
          colorCircleSecond: '#FBF8D7',
        })
      }
    }, 500)
  },
  //设置奖品 的位置与设置圆点位置的原理一样
  setAwardList() {
    //奖品item设置
    let awardList = [];
    //设置奖品容器相对于左上角定位点的距离
    let topAward = 0; //距离顶部
    let leftAward = 0; //距离左边
    for (let j = 0; j < 8; j++) {
      if (j == 0) {
        topAward = 190;
        leftAward = 122;
      } else if (j < 3) {
        topAward = topAward;
        //166.6666是宽.15是间距.下同
        leftAward = leftAward + 166 + 6;
      } else if (j < 5) {
        leftAward = leftAward;
        //150是高,15是间距,下同
        topAward = topAward + 150 + 6;
      } else if (j < 7) {
        leftAward = leftAward - 166 - 6;
        topAward = topAward;
      } else if (j < 8) {
        leftAward = leftAward;
        topAward = topAward - 150 - 6;
      }
      let awardItem = this.data.awardList[j];
      awardList.push({
        ...awardItem, //奖品对象
        topAward: topAward,
        leftAward: leftAward,
        isSelected: false, //默认false 未被选中
        isRemove: false, //默认false 未被选移除
      });
    }
    this.setData({
      awardList
    })
  },
  //开始游戏
  startGame() {
    // 如果不在抽奖状态中,则执行抽奖旋转动画
    if (this.data.isTurnOver) {
      // 把抽奖状态改为未完成
      this.setData({
        isTurnOver: false
      })
      this.getPrizeInfo()
      return;
    } else {
      wx.showToast({
        title: '请勿重复点击',
        icon: 'none'
      })
      return;
    }
  },
  getPrizeInfo() {
    // 这里开始假设已经调取后端接口拿到抽奖后返回的
    // 将ID与奖品的id进行对比 ,如果相等就返回奖品的索引index

    // 设置接口返回的ID为1 
    let id = 1
    let {
      awardList,
      indexSelect
    } = this.data
    awardList.forEach((item, index) => {
      if (item.awardId === id) {
        indexSelect = index + 1
        this.lottery(indexSelect);
      }
    })

    // 随机抽中第几个奖品
    // let {
    //   indexSelect
    // } = this.data
    // indexSelect = 1
    // this.lottery(indexSelect);
  },
  // 抽奖旋转动画方法
  async lottery(awardSort) {
    console.log('中的是第几个奖品:' + awardSort)
    // 如果不是第一次抽奖,需要等待上一圈没跑完的次数跑完再执行
    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, awardSort, order_arr);
        }, interval)
        //因为每一圈转完所用的时间是不一样的,所以要做一个叠加操作
        interval += delay * 8;
      })
    })
  },

  rotateCircle(delay, index, sum_rotate, awardSort, order_arr_pre) {
    // console.log("index", index)
    let _this = this;
    // 页面奖品总数组
    let prize_arr = this.data.awardList;
    // 执行顺序数组
    let order_arr = []
    // 如果转到最后以前,把数组截取到奖品项的位置
    if (index == sum_rotate) {
      order_arr = order_arr_pre.slice(0, awardSort)
    } else {
      order_arr = order_arr_pre;
    }
    for (let i = 0; i < order_arr.length; i++) {
      setTimeout(() => {
        // 清理掉选中的转态
        prize_arr.forEach(item => {
          item.isSelected = false
        })
        // 执行到第几个就改变它的选中状态
        prize_arr[i].isSelected = true;
        // 更新状态
        _this.setData({
          awardList: prize_arr
        })
        // 如果转到最后一圈且转完了,并且是非重置圈,把抽奖状态改为已经转完了
        if (index === sum_rotate && i === order_arr.length - 1 && !this.data.isRecover) {
          let timer = setTimeout(() => {
            _this.setData({
              isTurnOver: true,
              isRecover: true,
              awardSort_last: awardSort
            })
            clearInterval(timer)
          }, 1000)
        }
      }, 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 awardSort_last = this.data.awardSort_last; // 上一次抽奖的奖品序列
      // console.log(awardSort_last)
      order_arr = order_arr.slice(awardSort_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)
      })
    }
  },
})

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值