转盘抽奖主要有两种,指针转动和转盘转动,个人觉得转盘转动比较好看点,指针转动看着头晕,转盘转动时指针是在转盘的中间位置,这里要用到css的transform属性和transition属性,这两个因为不常用最好是上网查查,用法和功能。
在html部分
<div id="wheel_surf"> <div class="wheel_surf_title">幸运大转盘</div> <div class="lucky-wheel"> <div class="wheel-main"> <div class="wheel-pointer-box"> <div class="wheel-pointer" @click="rotate_handle()" :style="{transform:rotate_angle_pointer,transition:rotate_transition_pointer}"></div> </div> <div class="wheel-bg" :style="{transform:rotate_angle,transition:rotate_transition}"> <div class="prize-list"> <div class="prize-item" v-for="(item,index) in prize_list" :key="index"> <div class="prize-pic" v-if="item.icon"> <img :src="item.icon" /> </div> <div class="prize-type"> {{item.name}}</div> </div> </div> </div> </div> </div> <div v-transfer-dom> <x-dialog v-model="showHideOnBlur" class="dialog-demo wheel_dialog" hide-on-blur> <div class="img-box"> <div v-show="val == 7" class="noactive"> <p>谢谢参与!祝您下次好运</p> </div> <div v-show="val !== 7"> <p>恭喜你</p> <img :src="imgActive" /> <p>{{item.rewardDesc}}</p> // 获奖返回值 </div> </div> <div @click="showHideOnBlur=false"> <span class="vux-close"></span> </div> </x-dialog> </div> </div>
奖项数据
这里的第一个style部分是指针的位置,距离转动的初始值,是固定不变的,第二个style是转盘的位置transform:rotate_angle是转盘转动的角度,transition:rotate_transition是转动的时候它的转动速度,方向,等等属性。rotate_handle()是点击开始转动的事件。prize_list是转盘上面的奖品图片名字列表。
data:
prize_list: [ { icon: require("../../../../static/WX/img/wheel_big_5.png"), // 奖品图片 count: 5, // 奖品级别 name: "五等奖", // 奖品名称 isPrize: 1 // 该奖项是否为奖品 }, { icon: require("../../../../static/WX/img/wheel_big_2.png"), count: 2, name: "二等奖", isPrize: 1 }, { icon: require("../../../../static/WX/img/wheel_big_4.png"), count: 4, name: "四等奖", isPrize: 1 }, { icon: require("../../../../static/WX/img/wheel_big_1.png"), count: 1, name: "一等奖", isPrize: 1 }, { icon: require("../../../../static/WX/img/wheel_big_6.png"), count: 6, name: "六等奖", isPrize: 1 }, { count: 7, name: "谢谢参与", isPrize: 0 }, { icon: require("../../../../static/WX/img/wheel_big_3.png"), count: 3, name: "三等奖", isPrize: 1 }
], //奖品列表 hasPrize: false, //是否中奖 start_rotating_degree: 0, //初始旋转角度 rotate_angle: 0, //将要旋转的角度 start_rotating_degree_pointer: 0, //指针初始旋转角度 rotate_angle_pointer: 0, //指针将要旋转的度数 rotate_transition: "transform 6s ease-in-out", //初始化选中的过度属性控制 rotate_transition_pointer: "transform 12s ease-in-out", //初始化指针过度属性控制 click_flag: true, //是否可以旋转抽奖 item: {}
methods:
rotating(index) { if (!this.click_flag) return; var type = 0; // 默认为 0 转盘转动 1 箭头和转盘都转动(暂且遗留) var during_time = 5; // 默认为1s var random = Math.floor(Math.random() * 7); var result_index result_index = this.val if (this.val == 1) { // 这里多余可以不写 result_index = 3 } else if (this.val == 2) { result_index = 1 } else if (this.val == 3) { result_index = 6 } else if (this.val == 4) { result_index = 2 } else if (this.val == 5) { result_index = 0 } else if (this.val == 6) { result_index = 4 } else if (this.val == 7) { result_index = 5 } this.valindex = result_index // // 最终要旋转到哪一块 var result_angle = [18, 324, 275, 220, 175, 120, 64]; //最终会旋转到下标的位置所需要的度数,从指针初始位置开始算度数,顺时针或逆时针 var rand_circle = 6; // 附加多转几圈,2-3 this.click_flag = false; // 旋转结束前,不允许再次触发 if (type == 0) { // 转动盘子 var rotate_angle =this.start_rotating_degree + rand_circle * 360 +result_angle[result_index] - this.start_rotating_degree % 360; this.start_rotating_degree = rotate_angle; this.rotate_angle = "rotate(" + rotate_angle + "deg)"; var that = this; // 旋转结束后,允许再次触发 setTimeout(function() { that.click_flag = true; that.game_over(); }, during_time * 1000 + 1500); // 延时,保证转盘转完 } else { // } }
js部分主要是转动停止的角度rotate_angle ,第一次是从0开始到一个角度,在这个角度的基础上到下一个角度,所以会减去上一个角度对圆的取余,这里面this.val是代表着奖品等级,result_index是对应的旋转到的角度,因为旋转是顺时针,所以角度的选择要逆时针的选取。转完调用that.game_over();函数来获取奖品count等级。
下面方法为处理奖品数据
旋转停下来时调用game_over()函数
rotate_handle() { api.activityget(param).then(res => { if (res.status == 200 || res.status == '200') { this.item = res.data this.val = res.data.rewardLevel // 获取获奖等级 this.rotating(); //开始旋转 } else { this.$vux.alert.show({ title: '提示', content: res.message, }) } }) }
下面是css部分,根据你的奖品等级和数量自动调整距离左边和顶部距离和转动角度。
<style scoped> .wheel-main { display: flex; align-items: center; justify-content: center; position: relative; } .wheel-bg { width: 8rem; height: 8rem; background: url("../../../static/img/draw_wheel.png") no-repeat center top; background-size: 100%; color: #fff; font-weight: 500; display: flex; flex-direction: column; justify-content: center; align-content: center; transition: transform 3s ease; } .wheel-pointer-box { position: absolute; top: 50%; left: 50%; z-index: 100; transform: translate(-50%, -60%); } .wheel-pointer { width: 1.5rem; height:2.2rem; background: url("../../../static/img/btn_start_n.png") no-repeat ; background-size: 100%; transform-origin: center 60%; } .wheel-bg div { text-align: center; } .prize-list { width: 100%; height: 100%; position: relative; } .prize-list .prize-item { position: absolute; top: 0; left: 0; z-index: 2; } .prize-list .prize-item:first-child { top: .95rem; left: 2.9rem; transform: rotate(-20deg); } .prize-list .prize-item:nth-child(2) { top: 1.4rem; left: 5rem; transform: rotate(40deg); } .prize-list .prize-item:nth-child(3) { top: 3.2rem; left: 5.95rem; transform: rotate(-270deg); } .prize-list .prize-item:nth-child(4) { top: 5.08rem; left: 5.1rem; transform: rotate(-225deg); } .prize-list .prize-item:nth-child(5) { top: 5.8rem; left: 3.2rem; transform: rotate(-170deg); } .prize-list .prize-item:nth-child(6) { top: 4.7rem; left: 1.5rem; transform: rotate(-115deg); } .prize-list .prize-item:nth-child(6) .prize-type{ font-size: .3rem; } .prize-list .prize-item:nth-child(7) { top: 2.4rem; left: 1.2rem; transform: rotate(-69deg); } .prize-list .prize-item:nth-child(7) img{ width: .7rem; } .prize-list .prize-item:nth-child(8) { top: 1.1rem; left: 2.6rem; transform: rotate(-20deg); } .prize-pic img { width: .8rem; } .prize-count { font-size: .4rem; } .prize-type { font-size: 10px; } </style>