永远也抽不到奖的转盘

1,346 阅读2分钟

使用vue+grid布局

看看效果

  • 准备mock数据
  • 转盘的基本布局
  • 借助grid调整我们按钮位置
  • 开始抽奖

首先mock我们的中奖数据,中奖标识、奖品介绍、奖品图片等等。

const JP_OPTIONS = [
    {
      code: '1',
      name: '奖品1',
      imageName: '3q', //换上自己的img name
    },
    ...
]

基本布局方案,将我们的抽奖按钮项放置最后一位,借助index下标给我们的li定义不同的class name。

<template>
  <div class="dp-wrap">
    <ul class="u-wrap">
    	<li
          v-for="(jp, index) in jpList"
          :key="jp.code"
          :class="[{ active: jpIndex == index }, 'li-w-' + index]"
        >
          <img :src="jp.requireUrl" />
       	</li>
        <!-- 将抽奖按钮放在最后一位 -->
        <li class="now-w" @click="onStart"></li>
    </ul>
  </div>
</template>

挂载mock数据,实际是请求后端接口的数据。

export default {
  data() {
    let jpList = JP_OPTIONS.map((item) => {
      item.requireUrl = require(`@/assets/${item.imageName}.png`)	//加载本地的资源文件并转成base64
      return item
    })
    return {
      jpList,
      jpIndex: 0,	//抽奖开始项
    }
  }
}

grid布局, 资源加载可换成自己的图片,这时候我们可以借助grid布局任意组合我们的行和列,以便于我们调整li的位置。

@mixin li-w($gcs, $gce, $grs, $gre) {
  grid-column-start: $gcs;
  grid-column-end: $gce;
  grid-row-start: $grs;
  grid-row-end: $gre;
}

.dp-wrap {
  position: absolute;
  top: 0.4rem;
  left: 0.4rem;
  right: 0.4rem;
  // height: 6.82rem;
  background: url('~@/assets/dp.png');
  background-size: 100% 100%;
  background-repeat: no-repeat;
  padding: 0.34rem 0.34rem 0.52rem 0.34rem;
  box-sizing: border-box;
  .u-wrap {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(4, 1fr);
    grid-gap: 0.04rem 0.04rem;
    .active {
      background: url('~@/assets/win.png');
      background-size: 100% 100%;
      background-repeat: no-repeat;
    }
    > li {
      background: url('~@/assets/fail.png');
      background-size: 100% 100%;
      background-repeat: no-repeat;
      display: grid;
      grid-auto-flow: row;
      justify-content: center;
      justify-items: center;
      align-content: center;
      padding: 0.2rem 0 0.32rem;
      > p {
        font-size: 0.2rem;
        color: #3d79f3;
        margin-top: 0.14rem;
        text-align: center;
      }
      > img {
        // width: 100%;
        max-height: 0.94rem;
      }
    }
    /**/
    .li-w-3 {
      @include li-w(3, 4, 2, 3);
    }
    .li-w-4 {
      @include li-w(3, 4, 3, 4);
    }
    .li-w-5 {
      @include li-w(3, 4, 4, 5);
    }
    .li-w-6 {
      @include li-w(2, 3, 4, 5);
    }
    .li-w-7 {
      @include li-w(1, 2, 4, 5);
    }
    .li-w-8 {
      @include li-w(1, 2, 3, 4);
    }
    .li-w-9 {
      @include li-w(1, 2, 2, 3);
    }
    .now-w {
      background: url('~@/assets/jp.png');
      background-size: 100% 100%;
      background-repeat: no-repeat;
      @include li-w(2, 3, 2, 4);
    }
  }
}

接下来,借助JavaScript里的装饰者模式让转盘转动起来。

//定义一个class来维护我们的转动轨迹
class Luck {
  constructor() {
    this.index = 0; //当前转动到哪个位置,起点位置
    this.count = 10; //总共有多少个位置
    this.timer = 0; //setTimeout的ID
    this.speed = 20; //初始转动速度
    this.times = 0; //转动次数
    this.cycle = 50; //转动基本次数:即至少需要转动多少次再进入抽奖环节
    this.prize = -1; //中奖位置
    this.code = ''; //中奖奖品code
  }
  init(count, index) {
    if (count > 0) {
      this.count = count;
      this.index = index
    }
  }
  roll() {
    let index = this.index;
    let count = this.count;
    index += 1;
    if (index > count - 1) {
      index = 0;
    }

    this.index = index;
    return index;
  }
}

export default new Luck();
//onStart方法就是点击开始抽奖执行的
onStart() {
  luck.init(this.jpList.length, this.jpIndex)
  const test = '5'	//test就是我们后端返回的中奖项code,现在我们模拟让他是5
  luck.prize = this.jpList.findIndex((item) => item.code === test)	//匹配到我们的中奖项
  luck.code = test
  luck.speed = 100
  this.roll()
}
roll() {
  luck.times += 1
  this.jpIndex = luck.roll()
  if (luck.times > luck.cycle + 10 && luck.prize == luck.index) {
    clearTimeout(luck.timer)
    luck.prize = luck.prize
    luck.times = 0
    //已经中奖啦,这个时候就可以做我们中奖后的事情啦。。。
  } else {
    if (luck.times < luck.cycle) {
      luck.speed -= 10
    } else if (luck.times == luck.cycle) {
      luck.prize = luck.prize //最终中奖位置
    } else {
      if (
        luck.times > luck.cycle + 10 &&
        ((luck.prize == 0 && luck.index == 7) ||
          luck.prize == luck.index + 1)
      ) {
        luck.speed += 110
      } else {
        luck.speed += 20
      }
    }
    if (luck.speed < 40) {
      luck.speed = 40
    }
    luck.timer = setTimeout(this.roll, luck.speed)
  }
},

这样整个抽奖轮盘就可以转动起来了。

[grid布局参考]:(www.ruanyifeng.com/blog/2019/0…)