天天看点

九宫格抽奖代码实现

转盘抽奖demo

九宫格抽奖代码实现

核心代码

class Lottery {
    constructor(domId) {
        this.prizeIndexArr = [0, 1, 2, 5, 8, 7, 6, 3] // 顺时针转动对应的奖品序号
        this.maxStep = this.prizeIndexArr.length * 5 // 最大滚动的格子数
        this.currentIndex = -1 // 当前滚动到的格子的index
        this.step = 0 // 当前滚动过的格子总数
        this.timer = null
        this.speed = 200 // 初始速度
        this.domId = domId
        this.isStart = false // 是否已经开始抽奖,防止连续点击
    }

    doLottery = (prizeIndex) => {
        if (this.isStart) {
            return
        }
        this.startRoll(prizeIndex)
    }

    startRoll = (prizeIndex) => {
        this.isStart = true
        this.step += 1
        this.currentIndex += 1
        // 如果转到最后一个格子,则重置currentIndex为0,也就是从第一个格子继续转动
        if (this.currentIndex > 7) {
            this.currentIndex = 0
        }
        this.addActiveStyle()
        if (this.step >= this.maxStep + this.getIndex(prizeIndex) + 1 && prizeIndex === this.prizeIndexArr[this.currentIndex]) {
            clearTimeout(this.timer)
            this.step = 0
            this.speed = 200
            this.isStart = false
        } else {
            this.setSpeed(prizeIndex)
            this.timer = setTimeout(() => this.startRoll(prizeIndex), this.speed)
        }
    }

    /**
    * 给当前格子添加样式,取消前一个格子的样式,如果滚动到index为0的格子,则取消index为7的格子的样式
    */
    addActiveStyle = () => {
        const dom = document.getElementById(this.domId)
        // 这里可自行设置样式
        dom.children[this.prizeIndexArr[this.currentIndex]].style.background = 'yellow'
        if (this.currentIndex === 0) {
            dom.children[this.prizeIndexArr[7]].style.background = ''
        }
        if (this.currentIndex > 0) {
            dom.children[this.prizeIndexArr[this.currentIndex - 1]].style.background = ''
        }
    }

    /**
    * 设置转动的速度
    */
    setSpeed = (prizeIndex) => {
        // 前8个格子做加速运动
        if (this.step <= 8) {
            this.speed -= 20
        } else if (this.step >= this.maxStep + this.getIndex(prizeIndex) - 8) {
            // 后9个格子做减速运动
            this.speed += 60
        } else {
            this.speed = 40
        }
    }

    /**
    * 根据奖品的index找到prizeIndexArr对应的下标index
    * @returns {number}
    */
    getIndex = (prizeIndex) => {
        return this.prizeIndexArr.findIndex(item => item === prizeIndex)
    }
}

export default Lottery
           

页面使用

这里举在vue中的使用方法,react或其他原理一样

<template>
  <div class="lottery">
    <ul class="lottery-container" id="lottery-container">
      <li v-for="item in prizeList" :key="item.id" @click="doLottery(item.id)">
        {{ item.id === -1 ? "抽奖" : item.prizeName }}
      </li>
    </ul>
  </div>
</template>
<script>
import Lottery from "@/util/lottery";
export default {
  name: "lottery",
  setup() {
    const lottery = new Lottery("lottery-container");
    const prizeList = [
      { id: 1, prizeName: "mac pro" },
      { id: 2, prizeName: "吹风机" },
      { id: 3, prizeName: "电视机" },
      { id: 4, prizeName: "冰箱" },
      { id: -1 },
      { id: 5, prizeName: "优惠券" },
      { id: 6, prizeName: "华为手机" },
      { id: 7, prizeName: "电脑" },
      { id: 8, prizeName: "笔记本" },
    ];
    const doLottery = (id) => {
      if (id !== -1) return;
      const prizeIndex = Math.floor(Math.random() * 8 + 1)
      lottery.doLottery(prizeIndex);
    };
    return {
      prizeList,
      doLottery,
    };
  },
};
</script>
<style lang="scss" scoped>
.lottery-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  width: 3rem;
  height: 3rem;
  margin: 0 auto;

  li {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: calc(calc(100% / 3) - 0.1rem);
    height: 0.9rem;
    margin: 0.05rem;
    list-style: none;
    border-radius: 0.04rem;
    background-color: #eee;
    font-size: 0.16rem;

    &:nth-child(5) {
      background-color: #eb6a1a;
      cursor: pointer;
    }
  }
}
</style>

           

继续阅读