vue简单实现转盘抽奖

本文实例为大家分享了vue简单实现转盘抽奖的具体代码,供大家参考,具体内容如下

1.0 思路整理

转盘抽奖很常见,之前也没写过,现在有空来写写,分析如下:

1.1 转盘旋转 ----- 可以用 transform 的 rotate 来解决

1.2 旋转动画 ----- transition 过渡来处理

1.3 停留目标位置及中奖提示 ? ------ 通过控制旋转角度控制停留位置,中奖提示,考虑添加回调

1.1 开始行动

上面的思考,我们知道了大概要实现的步骤,首先我们搞张图片

这个圆盘有 10 份,每一份 360/10 = 36deg,假设要停留在第二个---->20金币,顺时针(含初始位置并计为1),即 共需要旋转 (2 - 1)* 36 = 36,这样,我们可以得出,停留位置需要旋转的角度 = (target - 1)*36。

1.2 中奖回调

上面的步骤,我们知道了如何控制到目标位置,那接下来就是事件通知,起初想的是,固定转动时间,然后开启定时器计时,很显然不靠谱,有没有什么可以在动画结束后就通知呢?transitionend,我找到了这个事件,可以监听元素动画结束事件,只不过有些兼容 这个好办

/**

动画结束事件兼容

**/

whichTransitionEvent(){

let el = document.createElement('span'),

transitions = {

'transition':'transitionend',

'OTransition':'oTransitionEnd',

'MozTransition':'transitionend',

'WebkitTransition':'webkitTransitionEnd'

};

for(let t in transitions){

if( el.style[t] !== undefined ){

return transitions[t];

}

}

el = null;

}

2.0 完整示例

控制转动位置和事件通知都找到方法了,接下来开干!

栗子:

完整代码

<template>

<div>

<h3>转盘抽奖</h3>

<div class="round_box" >

<img class="img_rotate" ref="rotImg" src="../assets/zhuan.png" alt="">

<div class="center">

<div class="pointer" ></div>

</div>

</div>

<button @click="toDraw" >点击抽奖</button>

</div>

</template>

<script>

export default {

name:'rotaryDraw',

data() {

return {

rotate: 0,

resetRotate: 0,

hitId: 1,// 1-10

drawStatus: false

}

},

async mounted() {

await this.$nextTick();

let evenTransition = this.whichTransitionEvent();

let img = this.$refs.rotImg;

let that = this;

const hitAre = [ '30M流量包','20金币','20M流量包','10M流量包','5金币',

'谢谢参与','10金币','50M流量包','2金币','100M流量包'

];

// 监听 动画结束

img.addEventListener(evenTransition,tranHand,false);

function tranHand() {

// 复位

that.resetRotate = that.rotate > 360 ? that.rotate % 360 : 0;

img.style.transition = "none 0s ease 0s";

img.style.transform = `rotate(${that.resetRotate}deg)`;

alert(`抽奖结果【 ${hitAre[that.hitId - 1]} 】`);

that.drawStatus = false

}

},

methods: {

start() {

this.$refs.rotImg.style.transition = "all 3s ease 0s";

this.$refs.rotImg.style.transform = `rotate(${this.rotate}deg)`;

},

toDraw() {

if(this.drawStatus){

console.log('正在抽奖中');

return

}

// 标记状态

this.drawStatus = true

/**

* 圆盘共 10 份 每份 36度, 停位置(id)度数 (id - 1)*36

* 基数 3圈 360*4

* this.rotate 当前角度

* **/

let reset = 360 * 4;

let idx = this.getRandomInt(1,11);

// 设置命中

this.hitId = idx;

// 需要多转角度

let addRotate = this.resetRotate > 0 ? 360 - this.resetRotate : 0;

// 总共角度

let allRotate = this.rotate + (idx - 1) * 36 + reset + addRotate;

// 角度限制

this.rotate = this.setRotate(allRotate);

this.start()

},

// 递归计算角度 不超过 360*6

setRotate(deg) {

let rest = deg - 360;

return rest > 360*6 ? this.setRotate(rest) : deg;

},

getRandomInt(min, max) {

// 向上收

min = Math.ceil(min);

// 向下收

max = Math.floor(max);

return Math.floor(Math.random() * (max - min)) + min; //不含最大值,含最小值

},

// 动画兼容

whichTransitionEvent(){

let el = document.createElement('span'),

transitions = {

'transition':'transitionend',

'OTransition':'oTransitionEnd',

'MozTransition':'transitionend',

'WebkitTransition':'webkitTransitionEnd'

};

for(let t in transitions){

if( el.style[t] !== undefined ){

return transitions[t];

}

}

el = null;

}

}

}

</script>

<style lang="scss" >

.img_rotate{

transform: rotate(0deg);

}

.round_box{

width: 100%;

max-width: 375px;

position: relative;

overflow: hidden;

img{

width: 100%;

}

.center{

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%,-50%);

.pointer{

width: 5px;

height: 90px;

background-color: #f40;

position: absolute;

top: -90px;

}

.pointer::before{

content:'';

width: 0;

height: 0;

border-top: 15px solid transparent;

border-right: 15px solid transparent;

border-bottom: 15px solid #f40;

border-left: 15px solid transparent;

position: absolute;

top: -20px;

left: 50%;

transform: translateX(-50%);

}

}

}

</style>

3.0 tips

总体来说有几个点需要注意

1、动画开始前上锁

2、动画结束后通知,状态复位

/**

比如:

基数3圈 reset 360*3

停留位置 第二个 (2 - 1)* 36 = 36

总共角度 360*3 + 36

动画停止后,因为还要继续旋转,所以不可能把角度一直增加,因此需要复位

360*3 + 36 其实可以考虑 就转了 36度,然后再增加需要转的角度

**/

3、继续旋转,因为我们计算是以 30M流量 为初始值的,所以在此旋转 仍然需要以 30M为起点,此时假设 现在停留位置是 300度,也就是说 再转 60度,也就回到了初始位置,本人也是按照这个思路进行复位的。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

以上是 vue简单实现转盘抽奖 的全部内容, 来源链接: utcz.com/p/238963.html

回到顶部