canvas实现扭蛋机动画效果的⽰例代码
转眼间,已经实习了两个⽉了,公司每个⽉都有个会员⽇的活动要做,这个⽉的任务是做⼀个扭蛋机抽奖的活动,数据什么的都有接⼝,那么前端剩下最⼤的任务就只剩下扭蛋机的动画实现了。
背景
本来兴⾼采烈地从⽹上了⼀个扭蛋机动画,但是发现它是直接⽤css动画,把扭蛋们的动画写死了,这样我不是很喜欢,于是还是选择⽤canvas绘制扭蛋的随机动画。先写了个简单的扭蛋机Demo,
开始
布局
扭蛋机的布局⽐较简单,只需要在基础背景上添加⼀些元素就可以,最主要的是canvas标签,其他都⽆所谓:
<div class="bg">
<span id="message">点击抽奖</span>
<div class="lotterybg">
<canvas id="myCanvas" width="285px" height="170px"></canvas>
<img src="img/lighting.png" class="lighting"/>
</div>
</div>
<img src="img/start-btn.png" id="start" onclick="play()"/>
<div class="award"><span id="awardBall"></span></div>
<img src="img/1.png" id="ball1" class="imgSrc">
<img src="img/2.png" id="ball2" class="imgSrc">
<img src="img/3.png" id="ball3" class="imgSrc">
<img src="img/4.png" id="ball4" class="imgSrc">
附上样式表:
body {margin: 0;padding: 0;border: none;}
.bg {background: url(../img/bg.png) top no-repeat;background-size: 100%;overflow: hidden;position: absolute;width: 400px;height: 100%;margin-top: 0;margin-left: 50%;-webkit-transform: translate(-50%);-moz-transform: translate(-50%);-ms-transform: translate(-5 #message {position: absolute;text-align: center;height: 25px;font-size: 22px;margin-top: 110px;margin-left: 50%;-webkit-transform: translate(-50%);-moz-transform: translate(-50%);-ms-transform: translate(-50%);-o-transform: translate(-50%);transform: translate( .lotterybg {background: url(../img/lotterybg.png) top no-repeat;background-size: 100%;overflow: visible;width: 80%;height: 100%;margin-top: 160px;margin-left: 50%;-webkit-transform: translate(-50%);-moz-transform: translate(-50%);-ms-transform: translate(-50% #myCanvas {position: absolute;border: none;width: 285px;height: 170px;margin-top: 15px;margin-left: 50%;-webkit-transform: translate(-50%);-moz-transform: translate(-50%);-ms-transform: translate(-50%);-o-transform: translate(-50%);transform: translate(-50% .lighting {display: block;max-width: 99%;margin-top: 0;margin-left: 0;}
#start {position: absolute;z-index: 3;width: 202px;margin-top: 413px;margin-left: 50%;-webkit-transfor
m: translate(-50%);-moz-transform: translate(-50%);-ms-transform: translate(-50%);-o-transform: translate(-50%);transform: translate(-50%);}
.imgSrc {display: none;position: absolute;}
.award {position: absolute;border: none;width: 60px;height: 200px;top: 470px;margin-left: 50%;-webkit-transform: translate(-50%);-moz-transform: translate(-50%);-ms-transform: translate(-50%);-o-transform: translate(-50%);transform: translate(-50%);}
这样⼦布局就算完成了,接下来主要⼯作就在canvas绘制图像上了。
扭蛋动画
先把各种变量定义好:
var canvas = ElementById('myCanvas');
var ctx = Context('2d');
var ball1 = ElementById('ball1');//图⽚对象
var ball2 = ElementById('ball2');//图⽚对象
var ball3 = ElementById('ball3');//图⽚对象
var ball4 = ElementById('ball4');//图⽚对象
var ballList = [ball1, ball2, ball3, ball4];//图⽚对象数组
var ballNum = 4;//扭蛋机⾥⾯的⼩球数
var awardList = [];//扭蛋机中的⼩球集合
var timer;//计时器
var award = ElementById('awardBall');
var message = ElementById('message');
扭蛋对象
扭蛋机⾥⾯每个扭蛋都是⼀个对象,所以需要定义⼀个扭蛋对象:
function Ball(index, img) {
this.r = 30;//⼩球半径
this.x = this.rand(canvas.width - this.r * 2);//⼩球初始横坐标
this.y = this.rand(canvas.height - this.r * 2);//⼩球初始纵坐标
this.img = img;//⼩球素材
do {
this.speedX = this.rand(20) - 10;
} while (this.speedX < 5);//⼩球横坐标改变速度
do {
this.speedY = this.rand(20) - 10;
} while (this.speedY < 5);//⼩球纵坐标改变速度
}
传⼊扭蛋对象的值index为⼩球的颜⾊,⽤数字1~4表⽰,img是图⽚对象,⽤来绘制扭蛋。
扭蛋⽅法
在上⼀步已经为扭蛋添加了属性,接下来就是给扭蛋添加⽅法:
Ball.prototype = {
rand: function (num) {//随机数
return Math.random() * num;
},
run: function () {//⼩球运动函数
this.x += this.speedX;
this.y += this.speedY;
if (this.x > canvas.width - this.r * 2) {//⼩球碰到右边界,横坐标速度变为负
this.speedX = -this.speedX;
}
if (this.x < 0) {//⼩球碰到左边界,横坐标速度变为正
this.speedX = Math.abs(this.speedX);
}
if (this.y > canvas.height - this.r * 2) {//⼩球碰到下边界,纵坐标速度变为负
this.speedY = -this.speedY;
}
if (this.y < 0) {//⼩球碰到上边界,纵坐标速度变为正
this.speedY = Math.abs(this.speedY);
}
ctx.drawImage(this.img, this.x, this.y, 60, 60);//绘制⼩球
}
}
主要是为扭蛋对象的原型添加上运动函数,运动函数的作⽤就是让扭蛋根据其速度动起来,并且在接触到边界的时候反弹。
初始化
接下来就是把扭蛋们放在扭蛋机⾥⾯:
function init() {//初始化
for (let i = 0; i < ballNum; i++) {//随机⽣成各⾊⼩球
let index = Math.floor(4 * Math.random());
awardList[i] = new Ball(index, ballList[index]);//新建⼩球对象
}
window.clearInterval(timer);//清除计时器
timer = setInterval(function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);//清空画布
for (let i = 0; i < awardList.length; i++) {
awardList[i].run();
}//使⼩球运动
}, 15);
}
这样⼦扭蛋机⾥⾯就已经有了⼩球。
开始扭蛋
开始扭蛋主要经历的过程就是点击按钮,扭蛋机扭蛋减少,获得相应扭蛋,中奖显⽰:
function play() {
if (awardList.length === 0) {//奖池中没有⼩球
alert('重新开始!');
init();
message.innerText = '点击抽奖';
} else {
window.clearInterval(timer);//清除计时器
let r = awardList.pop();//将奖池中的⼩球减少
timer = setInterval(function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);//清空画布
for (let i = 0; i < awardList.length; i++) {
awardList[i].run();
}//使⼩球运动
}, 15);
switch (r.color) {//⼩球掉落动画
case 0:
award.setAttribute('class', 'dropBall1');
break;
case 1:
award.setAttribute('class', 'dropBall2');
break;
case 2:
award.setAttribute('class', 'dropBall3');
break;
case 3:
award.setAttribute('class', 'dropBall4');
break;
}
setTimeout(function () {//扭蛋成功提⽰
award.setAttribute('class', '');
switch (r.color) {
case 0:
message.innerText = '紫球!';
break;
case 1:
message.innerText = '绿球!';
break;
case 2:
message.innerText = '黄球!';
break;
case 3:
message.innerText = '红球!';
break;
}
}, 1100);
}
}
在这⾥扭蛋的掉落动画使⽤css动画的关键帧来完成:
.dropBall1 {content: "";position: absolute;left: 0;top: 0;width: 60px;height: 60px;display: block;background: url(../img/1.png) no-repeat;background-size: contain;animation: drop 1s ease-out forwards;-webkit-animation: drop 1s ease-out forwards;} .dropBall2 {content: "";position: absolute;left: 0;top: 0;width: 60px;height: 60px;display: block;background: url(../img/2.png) no-repeat;background-size: contain;animation: drop 1s ease-out forwards;-webkit-animation: drop 1s ease-out forwards;} .dropBall3 {content: "";position: absolute;left: 0;top: 0;width: 60px;height: 60px;display: block;background: url(../img/3.png) no-repeat;background-size: contain;animation: drop 1s ease-out forwards;-webkit-animation: drop 1s ease-out forwards;} .dropBall4 {content: "";position: absolute;left:
0;top: 0;width: 60px;height: 60px;display: block;background: url(../img/4.png) no-repeat;background-size: contain;animation: drop 1s ease-out forwards;-webkit-animation: drop 1s ease-out forwards;} @keyframes drop {
0% {
transform: scale(0.7);
}
50% {
transform: scale(1);
}
51% {
transform: translateY(0px);
}
100% {
transform: translateY(100px);
}
}
@-webkit-keyframes drop {
0% {
-webkit-transform: scale(0.7);
}
50% {
-webkit-transform: scale(1);
}
51% {
-webkit-transform: translateY(0px);
}
canvas动画100% {
-webkit-transform: translateY(100px);
}
}
结束
当然,需要最后加上init();来让扭蛋机跑起来,到这⾥,这个简单的扭蛋机就算完成了,
总结
虽然这个Demo⽐较简单,但是还是有⼀些注意点和⼀些可优化的地⽅。
注意点
img对象
在html中的这些img标签:
<img src="img/1.png" id="ball1" class="imgSrc">
<img src="img/2.png" id="ball2" class="imgSrc">
<img src="img/3.png" id="ball3" class="imgSrc">
<img src="img/4.png" id="ball4" class="imgSrc">
样式也写成display: none;,这样写是为了在js中获取img对象,当然也可以不在html中写这些img标签,直接在js⽂件中写:
var img = new Image();
img.src = 'img/1.png';
这样⼦也可以得到img对象,也可以⽤来绘制扭蛋。
清除计时器
代码中清除计时器都是在调⽤计时器之前,之所以这样做的⽬的,是因为不清除计时器,计时器会⼀直计时,导致动画越来越⿁畜。
画布
在canvas画布上绘制可能会出现图像不清晰、放⼤的情况,这种情况可以通过将canvas标签的width和height属性设置成和样式的width和height属性相同来解决。以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论