这是一个使用CSS3和JavaScript实现的扭蛋机抽奖游戏。该游戏的主要功能是通过点击按钮进行抽奖,抽奖过程中会显示滚动的小球,最终随机停止并显示一个中奖小球。
这个游戏的实现方式是通过CSS3的动画效果和JavaScript的定时器来控制小球的滚动和抽奖的过程。使用CSS3可以轻松地实现小球的滚动效果,而JavaScript则可以控制抽奖的流程和时间。
html结构可根据自己需求重新开发,一下代码只是演示,抽奖思路,ball-box下面每个图片是根据index动态添加类名,在css中方便单独设置每个小球位置
<template>
<div>
<div class="raffle">
<div class="collectors">
<div class="top">Top 3 Xmas Balls Collectors</div>
<div class="awards-list">
<div class="item" v-for="(item, index) in emailList" :key="index">aaa@aaa.com</div>
</div>
</div>
<div class="lottery">
<!-- 抽奖 -->
<div class="ball-box" :class="{ 'active': !opportunityStatus }">
<img v-for="(item, index) in ballList" :key="index" :src="item" alt="" :class="`ball${index}`">
</div>
<!-- 抽奖次数 -->
<div class="glass">
<div class="glass-list">
<div class="item">1 MORE CHANCE</div>
</div>
<img src="./img/glass.png" alt="">
</div>
<!-- 滚动小球 -->
<img :src="lotteryBall" alt="" class="roll-ball" :class="{ 'active': rollBall }">
<img src="./img/ball-base.png" alt="" class="ball-base">
<img src="./img/games.png" alt="" class="games-img">
</div>
<!-- 抽奖按钮 -->
<div class="play" @click="rafflePlay">
<img src="./img/play-go.png" alt="">
</div>
</div>
</div>
</template>
flexible文件因为布局使用rem,来计算自适应,ballList数组中的图片可自行修改
<script>
export default {
data() {
return {
//抽奖小球
ballList:[
require('./img/ball-1.png'),
require('./img/ball-2.png'),
require('./img/ball-3.png'),
require('./img/ball-4.png'),
require('./img/ball-5.png'),
require('./img/ball-6.png'),
require('./img/ball-7.png'),
require('./img/ball-8.png'),
require('./img/ball-9.png'),
require('./img/ball-10.png'),
require('./img/ball-11.png'),
require('./img/ball-12.png'),
require('./img/ball-13.png'),
require('./img/ball-14.png'),
],
opportunityStatus:true,//抽奖状态,抽奖按钮是否能点击
}
},
mounted() {
import("public/js/flexible").then(() => {
})
},
methods: {
rafflePlay(){
//判断当前是否在执行抽奖任务 当前出现的小球没有消失之前不能点击抽奖
if(!this.opportunityStatus || this.rollBall) return
this.opportunityStatus=false
//抽奖进行4秒后停止出现出奖小球
setTimeout(()=>{
this.opportunityStatus=true
//结束抽奖随机滚动出现一个小球
this.lotteryBall=this.ballList[Math.floor(Math.random()*13)]
//开始滚动小球
this.rollBall=true
//小球到最终位置后隐藏,这里的计时器,要比css中写的运动轨迹时间长一点,不然没有到终点小球就已经隐藏了
setTimeout(()=>{
this.rollBall=false
},5000)
},4000)
},
}
}
</script>
@keyframes动效,这里我只列出了两个小球的运动轨迹,可自行添加
<style scoped lang="scss">
.raffle {
width: 12.24rem;
height: 9.01rem;
background-color: #000;
background-size: 100% 100%;
border-radius: 0.6rem;
padding-top: 0.67rem;
box-sizing: border-box;
margin: auto;
position: relative;
.title {
display: block;
margin: auto;
height: 0.46rem;
width: auto;
}
.collectors {
position: absolute;
right: -1.23rem;
top: .64rem;
width: 3.67rem;
height: 1.61rem;
background-image: url('../../../../img/cyberxmas/awards-bg.png');
background-size: 100% 100%;
.top {
font-size: 0.2rem;
font-weight: 400;
color: #8BFFFB;
text-align: center;
padding-top: 0.62rem;
box-sizing: border-box;
}
.awards-list {
position: absolute;
bottom: 0.23rem;
margin: auto;
right: 0;
left: 0;
height: 0.15rem;
padding: 0.1rem 0;
overflow: hidden;
.item {
text-align: center;
font-size: 0.19rem;
margin-bottom: 0.1rem;
color: rgba(255, 255, 255, 0.83);
-webkit-animation: 5s rowup linear infinite normal;
animation: 5s rowup linear infinite normal;
}
}
}
.lottery {
width: 5.78rem;
height: 5.82rem;
margin: auto;
margin-top: 0.33rem;
position: relative;
.ball-box {
position: absolute;
right: 0;
left: 0;
top: -0.1rem;
height: 3.68rem;
width: 3.52rem;
border-radius: 68%;
margin: auto;
padding: 0.6rem;
position: relative;
img {
height: 0.88rem;
width: auto;
position: absolute;
}
.ball0 {
transform: translate(-0.15rem, 1.6rem) rotate(0deg);
}
.ball1 {
transform: translate(-.1rem, 2.2rem) rotate(0deg);
}
.ball2 {
transform: translate(.6rem, 2.5rem) rotate(0deg);
z-index: 1;
}
.ball3 {
transform: translate(.6rem, 1.7rem) rotate(0deg);
}
.ball4 {
transform: translate(1rem, 2.1rem) rotate(0deg);
z-index: 1;
}
.ball5 {
transform: translate(1.4rem, 2.2rem) rotate(0deg);
z-index: 1;
}
.ball6 {
transform: translate(1.4rem, 1.5rem) rotate(0deg);
z-index: 1;
}
.ball7 {
transform: translate(1.8rem, 1.9rem) rotate(0deg);
}
.ball8 {
transform: translate(2.3rem, 2.4rem) rotate(0deg);
}
.ball9 {
transform: translate(2.1rem, 1rem) rotate(0deg);
}
.ball10 {
transform: translate(2.5rem, 1.7rem) rotate(0deg);
}
.ball11 {
transform: translate(2.8rem, 1.7rem) rotate(0deg);
}
.ball12 {
transform: translate(2.9rem, 2.1rem) rotate(0deg);
}
.ball13 {
transform: translate(3rem, 1.2rem) rotate(0deg);
}
&.active {
@for $i from 0 through 13 {
.ball#{$i} {
animation: around#{$i} 6s linear infinite;
}
}
}
}
.roll-ball {
width: 0.43rem;
height: auto;
position: absolute;
top: 2rem;
left: 0.5rem;
transform: translate(2.2rem, 2.97rem) rotate(0deg) scale(1.4);
display: none;
&.active {
display: block;
animation: rollball 3s linear;
z-index: 2;
}
}
.ball-base {
width: 4.39rem;
height: 1.5rem;
display: block;
position: absolute;
left: 0.69rem;
bottom: 0.2rem;
z-index: 4;
}
.glass {
width: 2.37rem;
height: 0.36rem;
position: absolute;
bottom: 1.78rem;
left: 1.73rem;
font-size: 0.18rem;
text-align: center;
line-height: 0.36rem;
color: #FFFFFF;
opacity: 0.86;
z-index: 5;
overflow: hidden;
.glass-list {
display: flex;
.item {
width: 2.4rem;
white-space: nowrap;
}
}
img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
}
.games-img {
position: absolute;
top: 0;
left: 0;
z-index: 1;
width: 100%;
height: 100%;
}
}
.play {
width: 1.47rem;
height: 0.69rem;
margin: auto;
cursor: pointer;
margin-top: 0.27rem;
&:hover {
opacity: 0.6;
}
img {
width: 100%;
height: 100%;
display: block;
}
}
//奖品展示
.prize-left,
.prize-right {
width: 1.22rem;
position: absolute;
left: 1.14rem;
bottom: 1.16rem;
li {
width: 100%;
height: 1.56rem;
background: rgba(118, 73, 175, 0.37);
border: 0.02rem solid #5F4C86;
border-radius: 0.08rem;
display: flex;
align-items: center;
justify-content: center;
margin-top: 0.13rem;
position: relative;
.tips {
position: absolute;
top: -0.38rem;
padding: 0.18rem;
box-sizing: border-box;
background: rgba(0, 0, 0, 0.42);
border: 0.02rem solid #948CA4;
border-radius: 0.02rem;
font-size: 0.16rem;
color: #FFFFFF;
text-align: center;
white-space: nowrap;
display: none;
}
&:hover {
.tips {
display: block;
}
}
img {
height: auto;
}
&:nth-child(1) {
img {
width: 0.64rem;
}
}
&:nth-child(2) {
img {
width: 0.77rem;
}
}
&:nth-child(3) {
img {
width: 0.4rem;
}
}
}
}
.prize-right {
right: 1.07rem;
left: initial;
li:nth-child(1) {
img {
width: 0.84rem;
}
}
li:nth-child(2) {
img {
width: 1.03rem;
}
}
li:nth-child(3) {
img {
width: 0.91rem;
}
}
}
}
@keyframes around0 {
0% {
transform: translate(0rem, 1.6rem) rotate(0deg);
}
5% {
transform: translate(1.28rem, .1rem) rotate(50deg);
}
10% {
transform: translate(.2rem, .43rem) rotate(70deg);
}
15% {
transform: translate(.28rem, .2rem) rotate(260deg);
}
20% {
transform: translate(.2rem, .8rem) rotate(80deg);
}
25% {
transform: translate(0.9rem, -.1rem) rotate(140deg);
}
30% {
transform: translate(1.2rem, .9rem ) rotate(60deg);
}
35% {
transform: translate(2.2rem, -0.1rem) rotate(260deg);
}
40% {
transform: translate(0.8rem, .27rem) rotate(260deg);
}
45% {
transform: translate(2.1rem, 0.5rem) rotate(0deg);
}
50% {
transform: translate(3rem, 1.5rem) rotate(0deg);
}
55% {
transform: translate(0.82rem, -.1rem) rotate(50deg);
}
60% {
transform: translate(.29rem, .2rem) rotate(70deg);
}
65% {
transform: translate(.7rem, .9rem) rotate(260deg);
}
70% {
transform: translate(1rem, .4rem) rotate(80deg);
}
75% {
transform: translate(.7rem, 1.4rem) rotate(140deg);
}
80% {
transform: translate(1.1rem, -.2rem) rotate(60deg);
}
85% {
transform: translate(1rem, .6rem) rotate(260deg);
}
90% {
transform: translate(2.6rem, 1.1rem) rotate(260deg);
}
95% {
transform: translate(.1rem, 1.4rem) rotate(0deg);
}
100% {
transform: translate(-0.15rem, 1.6rem) rotate(0deg);
}
}
// ...... 0_13
@keyframes around13 {
0% {
transform: translate(3rem, 1.2rem) rotate(0deg);
}
5% {
transform: translate(1.2rem, 0.4rem) rotate(260deg);
}
10% {
transform: translate(.3rem, 2.3rem) rotate(70deg);
}
15% {
transform: translate(2.3rem, 0rem) rotate(260deg);
}
20% {
transform: translate(3rem, 2.1rem) rotate(260deg);
}
25% {
transform: translate(0.4rem, .1rem) rotate(140deg);
}
30% {
transform: translate(2.7rem, 1.3rem ) rotate(60deg);
}
35% {
transform: translate(2.28rem, 2.1rem) rotate(50deg);
}
40% {
transform: translate(.64rem, .1rem) rotate(260deg);
}
45% {
transform: translate(-0.3rem, 2rem) rotate(0deg);
}
50% {
transform: translate(1.5rem, -0.2rem) rotate(0deg);
}
55% {
transform: translate(2rem, 2.2rem) rotate(60deg);
}
60% {
transform: translate(.2rem, 0.1rem) rotate(70deg);
}
65% {
transform: translate(2rem, 2rem) rotate(260deg);
}
70% {
transform: translate(2.1rem, .3rem) rotate(260deg);
}
75% {
transform: translate(3rem, 2.1rem) rotate(140deg);
}
80% {
transform: translate(.2rem, 0.2rem) rotate(50deg);
}
85% {
transform: translate(1.5rem, 1.8rem) rotate(80deg);
}
90% {
transform: translate(2.4rem, .2rem) rotate(80deg);
}
95% {
transform: translate(1rem, 2.2rem) rotate(0deg);
}
100% {
transform: translate(3rem, 1.2rem) rotate(0deg);
}
}
@keyframes rollball{
0%{
transform: translate(-.0rem, 0) rotate(0deg);
}
5%{
transform: translate(-.28rem, 0) rotate(260deg);
}
10%{
transform: translate(-.38rem, 0) rotate(70deg);
}
15%{
transform: translate(-.48rem, 0) rotate(260deg);
}
20%{
transform: translate(-.48rem, .2rem) rotate(260deg);
}
25%{
transform: translate(-.48rem, .3rem) rotate(140deg);
}
30%{
transform: translate(-.48rem, .4rem) rotate(60deg);
}
35%{
transform: translate(-.48rem, .7rem) rotate(50deg);
}
40%{
transform: translate(-.48rem, 1rem) rotate(260deg);
}
45%{
transform: translate(-.48rem, 1.2rem) rotate(0deg);
}
50%{
transform: translate(-.48rem, 1.5rem) rotate(0deg);
}
55%{
transform: translate(-.48rem, 1.7rem) rotate(60deg);
}
60%{
transform: translate(-.48rem, 2.07rem) rotate(70deg);
}
65%{
transform: translate(-.48rem, 2.57rem) rotate(260deg);
z-index: 2;
}
70%{
transform: translate(-.28rem, 2.57rem) rotate(260deg);
z-index: 2;
}
75%{
transform: translate(.6rem, 2.97rem) rotate(140deg);
z-index: 2;
}
80%{
transform: translate(1rem, 2.97rem) rotate(50deg);
z-index: 2;
}
85%{
transform: translate(1.58rem, 2.97rem) rotate(80deg);
z-index: 2;
}
90%{
transform: translate(1.78rem, 2.97rem) rotate(80deg);
z-index: 2;
}
95%{
transform: translate(2.2rem, 2.97rem) rotate(0deg) scale(1.4);
z-index: 2;
}
100%{
transform: translate(2.2rem, 2.97rem) rotate(0deg) scale(1.4);
z-index: 2;
}
}
</style>
最终效果就是上面视频的demo