转眼间,已经实习了两个月了,公司每个月都有个会员日的活动要做,这个月的任务是做一个扭蛋机抽奖的活动,数据什么的都有接口,那么前端剩下最大的任务就只剩下扭蛋机的动画实现了。
背景
本来兴高采烈地从网上找了一个扭蛋机动画,但是发现它是直接用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(-50%);-o-transform: translate(-50%);transform: translate(-50%);} #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(-50%);} .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%);-o-transform: translate(-50%);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-transform: 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 = document.getElementById('myCanvas'); var ctx = canvas.getContext('2d'); var ball1 = document.getElementById('ball1');//图片对象 var ball2 = document.getElementById('ball2');//图片对象 var ball3 = document.getElementById('ball3');//图片对象 var ball4 = document.getElementById('ball4');//图片对象 var ballList = [ball1, ball2, ball3, ball4];//图片对象数组 var ballNum = 4;//扭蛋机里面的小球数 var awardList = [];//扭蛋机中的小球集合 var timer;//计时器 var award = document.getElementById('awardBall'); var message = document.getElementById('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.color = index;//小球颜色,以下标表示 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); } 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属性相同来解决。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
P70系列延期,华为新旗舰将在下月发布
3月20日消息,近期博主@数码闲聊站 透露,原定三月份发布的华为新旗舰P70系列延期发布,预计4月份上市。
而博主@定焦数码 爆料,华为的P70系列在定位上已经超过了Mate60,成为了重要的旗舰系列之一。它肩负着重返影像领域顶尖的使命。那么这次P70会带来哪些令人惊艳的创新呢?
根据目前爆料的消息来看,华为P70系列将推出三个版本,其中P70和P70 Pro采用了三角形的摄像头模组设计,而P70 Art则采用了与上一代P60 Art相似的不规则形状设计。这样的外观是否好看见仁见智,但辨识度绝对拉满。
更新日志
- 英雄联盟六个龙魂是哪六个 英雄联盟六个龙魂介绍一览
- 《忆蚀》Subliminal:揭秘后室之谜,路知行献声Weplay文化展
- 初始之部制作人气漫画改编游戏《我家大师兄脑子有坑》参展2024WePlay
- 《异环》「奇点测试」定档11.28 超自然都市轻喜剧即将放送!
- 16层乐队.2024-大快朵颐【摩登天空】【FLAC分轨】
- 群星.1988-电视金曲巡礼【EMI百代】【WAV+CUE】
- 群星.1992-电视金曲巡礼VOL.2【EMI百代】【WAV+CUE】
- 廖昌永《情缘HQ》头版限量[低速原抓WAV+CUE]
- 蔡琴《老歌》头版限量编号MQA-24K金碟[低速原抓WAV+CUE]
- 李嘉《国语转调》3CD[WAV+CUE]
- 谭咏麟《爱的根源 MQA-UHQCD》2022头版限量编号 [WAV+CUE][1G]
- 江洋 《江洋原创琵琶作品专辑》[320K/MP3][118.08MB]
- 江洋 《江洋原创琵琶作品专辑》[FLAC/分轨][228.33MB]
- 《战舰世界》语音包文件夹位置介绍
- 《CSGO》送好友皮肤方法介绍