vue中实现大转盘抽奖灯光闪烁

官方文档入口

一. 在 Vue 中使用

  1. 安装插件
npm install vue-luck-draw
  1. 找到 main.js 全局引入插件并 use,或者在组件中按需引入插件。
// 按需引入
import { LuckyWheel } from 'vue-luck-draw'
Vue.components('LuckyWheel', LuckyWheel)
  1. 最后在页面内使用 <LuckyWheel />大转盘组件,根据官方文档想要的配置参数

二. 转盘抽奖正常流程

1. 当你点击抽奖按钮时触发strat回调函数,接下来你可以调用play()方法先让大转盘转起来,然后紧接着去请求接口拿数据,或是你自己随机一个index
2. 当接口拿到index中奖索引之后,你就可以调用stop(index)方法了,此时大转盘会缓慢停止,当完全停止之后就会触发end回调函数(当接口返回的速度很快的时候,会跳过匀速阶段,此时可手动加一个定时器延缓调用的时机)
3. 最后在end回调函数里面,得到中奖奖品的全部信息,你就可以在这里执行逻辑告诉用户他中奖了

三. 转盘灯光闪烁

根据判断条件替换背景图,需要注意的是需要提前加载出背景图,不然会闪烁一下

背景图闪烁的原因:

1)博主是通过class三元表达式,来引入不同的class,引入不同的背景图片实现灯光闪烁的。
:class="[imgIndex == 1 ? 'changeImg_one' : 'changeImg_two']"
.changeImg_one {
    background: url("../../assets/image/luckly/xx.png") no-repeat;
  }2)这种通过class加载的方式,默认是使用changeImg_one这个class,所以changeImg_one对应的图片是
正常加载的,而changeImg_two这个class是通过点击方法来切换的。所以就导致changeImg_two的背景图
没加载出来,点击需要重新去加载图片,然后替换,出现闪烁。
(3)预防方案
  使用图片预加载,就是在实际点击抽奖之前,就把两张灯光的图片都加载到浏览器缓存。可以使用 
  new Image()对象,或者一进入页面就加载的方式。
(4)博主这里是直接通过img标签引入背景图,然后定位。这样vue就会自动加载img图片,然后我们通过
  v-show来控制即可

代码如下:

<template>
  <div class="wrap">
    <div class="lucky_wheel">
      <img
        class="lucky_title"
        src="../../assets/image/luckly/written words.png"
      />
      <div class="wheel_main">
        <LuckyWheel
          class="role"
          ref="LuckyWheel"
          width="6.48rem"
          height="6.48rem"
          :prizes="prizes"
          :buttons="buttons"
          :default-style="defaultStyle"
          @start="startCallBack"
          @end="endCallBack"
        />
        <div class="count_info">
          还可抽奖<span class="count">{{ count }}</span>
        </div>
        <img
          class="lotteryBorder"
          v-show="imgIndex === 1"
          src="../../assets/image/luckly/turntable.png"
        />
        <img
          class="lotteryBorder"
          v-show="imgIndex === 2"
          src="../../assets/image/luckly/turntable_lights.png"
        />
      </div>
    </div>
    <div class="tip_con">
      <img
        class="tip_btn"
        src="../../assets/image/luckly/activity details.png"
      />
      <div class="tip_content">
        <div class="tip_item">
          <div class="img_num">
            <span class="number">1</span>
          </div>
          <p>
            活动细则活动细则活动细则活动细则活动细则活动细则活动细则活动细则
          </p>
        </div>
        <div class="tip_item">
          <div class="img_num">
            <span class="number">2</span>
          </div>
          <p>
            活动细则活动细则活动细则活动细则活动细则活动细则活动细则活动细则
          </p>
        </div>
      </div>
      <img class="logo" src="../../assets/image/luckly/luckly-logo.png" />
      <van-overlay :show="verifyDialogShow">
        <div class="overlayMain">
          <div class="overlay_title">中奖信息</div>
          <div class="info">
            {{ overlayInfo }}
          </div>
          <div class="confirm" @click="confirm">确认</div>
        </div>
      </van-overlay>
    </div>
  </div>
</template>

<script>
import { LuckyWheel } from "vue-luck-draw";
import { Overlay } from "vant";
export default {
  data() {
    return {
      prizes: [],
      buttons: [
        {
          radius: "30%",
          imgs: [
            {
              src: require("../../assets/image/luckly/luckly_btn.png"),
              width: "200%",
              top: "-185%"
            }
          ]
        }
      ],
      defaultStyle: {
        fontSize: "10px",
        fontColor: "#EC652D"
      },
      verifyDialogShow: false,
      count: 0, // 剩余抽奖次数
      winId: "", //获取奖品的id
      winName: "", //中奖奖品名字
      mid: 999,
      currentIndex: 0 //抽中数组中第几个奖品
    };
  },
  computed: {
    overlayInfo() {
      return this.winId > 0 ? `恭喜你获得${this.winName}` : "谢谢参与";
    }
  },
  created() {
    this.getPrizesList();
  },
  // mounted() { //让灯光闪烁的另一种办法,用的时候去掉html里的两个img标签就好
  //   var temp_timer = setInterval(this.changeImg, 100);
  //   setTimeout(() => {
  //     clearInterval(temp_timer);
  //   }, 300);
  // },
  methods: {
    getPrizesList() {
      let data = [
        {
          id: "12",
          name: "奖品1",
          image: require("../../assets/image/luckly/doubledouzi.png")
        },
        {
          id: "24",
          name: "奖品2",
          image: require("../../assets/image/luckly/douzi.png")
        },
        {
          id: "3",
          name: "奖品3",
          image: require("../../assets/image/luckly/pinggai.png")
        },
        {
          id: "14",
          name: "奖品4",
          image: require("../../assets/image/luckly/double_pinggai.png")
        },
        {
          id: "5",
          name: "奖品5",
          image: require("../../assets/image/luckly/qiandai.png")
        },
        {
          id: "6",
          name: "奖品6",
          image: require("../../assets/image/luckly/qiandai.png")
        }
      ];
      this.dataList = data;
      this.count = 2;
      var thanks_obj = {
        id: "0",
        name: "谢谢参与",
        image: require("../../assets/image/luckly/thank.png")
      };
      if (this.dataList.length % 2 == 1) {
        //如果数组是奇数的话,直接在数组最前面添加谢谢参与,为了转盘背景颜色是间隔的
        this.dataList.unshift(thanks_obj);
      } else {
        //如果数组是偶数的话,在数组最前面和数组中间添加谢谢参与
        this.mid = this.dataList.length / 2;
        this.dataList.splice(this.mid, 0, thanks_obj);
        this.dataList.unshift(thanks_obj);
      }
      console.log(this.dataList);
      this.dataList.forEach((item, index) => {
        this.prizes.push({
          name: item.name,
          background: index % 2 ? "#FFD787" : "#fff",
          fonts: [
            {
              text: item.name,
              top: "10px"
            }
          ],
          imgs: [
            {
              src: item.image,
              width: "35px",
              // top: "30px",
              // width: "25%",
              top: "30%"
            }
          ]
        });
      });
    },
    startCallBack() {
      //没有抽奖次数return出去
      if (this.count == 0) {
        this.$toast("没有抽奖次数了");
        return;
      }
      this.count--;
      this.$refs.LuckyWheel.play();

      this.winId = parseInt("5"); //模拟接口,这里转换为number类型
      //留出匀速的时间
      setTimeout(() => {
        if (this.winId == 0) {
          this.$refs.LuckyWheel.stop(0); //如果winId=0,直接取数组里的第一个
        } else {
          this.dataList.forEach((item, index) => {
            //否则循环数组,拿中奖奖品id去数组里item.id比对,如果两个id值相等的话,就取数组当前的索引,赋值给 this.currentIndex
            if (item.id == this.winId) {
              this.currentIndex = index;
              console.log(index);
            }
          });
          this.$refs.LuckyWheel.stop(this.currentIndex);
          //一开始用的下面这种取索引方法,发现不行,因为当时想象的是id从1开始,依次排列。但是在真正项目中,id会打乱
          //如果是数组长度是奇数的话走if,偶数的话多加了两个谢谢参与,中间谢谢参与之前的索引走if;之后的索引取值走else
          // if (this.winId <= this.mid) {  
          //   this.$refs.LuckyWheel.stop(this.winId);
          // } else {
          //   this.$refs.LuckyWheel.stop(this.winId + 1);
          // }
        }
      }, 3000);
    },
    endCallBack(prize) {
      this.winName = prize.name;
      this.verifyDialogShow = true;
    },

    confirm() {
      this.verifyDialogShow = false;
    }
  },
  components: {
    VanOverlay: Overlay,
    LuckyWheel: LuckyWheel
  }
};
</script>

<style lang="scss" scoped>
.lucky_wheel {
  height: 572px;
  background: url("../../assets/image/luckly/background_2.png") no-repeat;
  background-size: cover;
  .lucky_title {
    width: 312px;
    margin: 0 auto;
    padding-top: 13px;
  }
  .wheel_main {
    position: relative;
    background: url("../../assets/image/luckly/turntable.png") no-repeat;
    background-size: cover;
    width: 345px;
    height: 399px;
    margin: -8px auto;
    .role {
      // width: 243px;
      // height: 243px;
      // border-radius: 500px;
      position: absolute;
      top: 50px;
      left: 51px;
      // overflow: hidden;
    }
    .count_info {
      position: absolute;
      bottom: 14px;
      left: 50%;
      transform: translateX(-50%);
      color: #fff;
      text-align: center;
      margin-top: -30px;
      letter-spacing: 3px;
      font-size: 12px;
      .count {
        color: #ffc47c;
        font-weight: bold;
      }
      .lotteryBorder {
        position: absolute;
        width: 345px;
        height: 399px;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
      }
    }
  }
}
.tip_con {
  height: auto;
  background: url("../../assets/image/luckly/background_3.png") no-repeat;
  background-size: 100% 100%;
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  position: relative;
  .tip_btn {
    position: absolute;
    top: -26px;
    width: 292px;
    height: 59px;
  }
  .tip_content {
    background: url("../../assets/image/luckly/rule_bg.png") no-repeat;
    background-size: 100% 100%;
    width: 344px;
    height: auto;
    padding: 50px 14px 30px 14px;
    box-sizing: border-box;
    border-radius: 5px;
    .tip_item {
      display: flex;
      margin-bottom: 8px;
      .img_num {
        background: url("../../assets/image/luckly/digital.png") no-repeat;
        background-size: cover;
        width: 20px;
        height: 20px;
        display: flex;
        justify-content: center;
        align-items: center;
        margin-right: 5px;
      }
      .number {
        font-size: 13px;
        color: #de192e;
      }
      p {
        flex: 1;
        color: #fcf6ef;
        letter-spacing: 1px;
        line-height: 16px;
        font-size: 12px;
      }
    }
  }
  .logo {
    margin: 25px auto 44px;
    width: 90px;
    height: 21px;
  }
  .overlayMain {
    width: 90%;
    height: auto;
    border-radius: 12px;
    background: #fff;
    position: absolute;
    top: 200px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    align-items: center;
    flex-direction: column;
    .overlay_title {
      padding-top: 26px;
      font-size: 16px;
      font-weight: bold;
    }
    .info {
      font-size: 14px;
      padding: 8px 24px 26px;
      text-align: center;
    }
    .confirm {
      width: 100%;
      height: 48px;
      line-height: 48px;
      border-top: 1px solid #ebedf0;
      color: #ee0a24;
      font-size: 16px;
      text-align: center;
    }
  }
}
</style>

三. 遇到的bug

1)转盘抽奖这里遇到一个bug,点击指针让转盘转的时候,ios上需要点击两下,安卓上是正常的
排查问题发现是用的vant dialog弹窗组件的问题,更换成Overlay 遮罩层组件问题就解决了

2)灯光闪烁这里是通过判断条件来替换转盘背景图,但是每次在页面刚进来时候点击转盘按钮让转盘转起来,背景图就会闪烁一下,解决方法就是先让需要切换的这张背景图提前加载出来
目前我用了两种方法都实现了:
方法一:
.html里新增两个img标签,给它定好位置和原来转盘背景图吻合;再条件判断下,当imgIndex === 1时,展示第一张;imgIndex === 2时,展示第二张;相当于提前用img标签加载出来了
方法二:
vue的mounted生命周期函数里,setInterval定时器提前开启背景图

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

铁锤妹妹@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值