In the blink of an eye, I have been an intern for two months. The company has a membership day event every month. This month’s task is to do a gashapon machine lottery event. There are interfaces for data and so on, so what is left on the front end? The biggest task was just to realize the animation of the gashapon machine.
backgroundI was excited to find a gashapon machine animation from the Internet, but I found that it used CSS animation directly to write the animation of the gashapon to death. I didn't like it very much, so I chose to use canvas to draw the random animation of the gashapon. First I wrote a simple gashapon machine demo and preview the effect.
start layoutThe layout of the gashapon machine is relatively simple. You only need to add some elements to the basic background. The most important thing is the canvas tag. Everything else does not matter:
<div class=bg> <span id=message>Click to draw</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>
Attached style sheet:
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%);}
In this way, the layout is completed, and the next main work is to draw the image on the canvas.
Gacha animationFirst define the various variables:
var canvas = document.getElementById('myCanvas');var ctx = canvas.getContext('2d');var ball1 = document.getElementById('ball1');//Picture object var ball2 = document.getElementById('ball2' );//Picture object var ball3 = document.getElementById('ball3');//Picture object var ball4 = document.getElementById('ball4');//Picture object var ballList = [ball1, ball2, ball3, ball4];//Picture object array var ballNum = 4;//The number of balls in the gashapon machine var awardList = [ ];//The collection of small balls in the gashapon machine var timer;//Timer var award = document.getElementById('awardBall'); var message = document.getElementById('message');Gacha object
Each gashapon in the gashapon machine is an object, so you need to define a gashapon object:
function Ball(index, img) { this.r = 30;//The radius of the ball this.x = this.rand(canvas.width - this.r * 2);//The initial abscissa of the ball this.y = this .rand(canvas.height - this.r * 2);//The initial vertical coordinate of the ball this.color = index;//The color of the ball, represented by the subscript this.img = img;//The ball material do { this .speedX = this.rand(20) - 10; } while (this.speedX < 5);//The ball’s abscissa changes speed do { this.speedY = this.rand(20) - 10; } while (this.speedY < 5);//The vertical coordinate of the ball changes speed}
The value index of the incoming gashapon object is the color of the ball, represented by numbers 1 to 4, and img is the image object used to draw the gashapon.
Gacha methodIn the previous step, attributes have been added to the gashapon. The next step is to add methods to the gashapon:
Ball.prototype = { rand: function (num) {//Random number return Math.random() * num; }, run: function () {//Ball motion function this.x += this.speedX; this. y += this.speedY; if (this.x > canvas.width - this.r * 2) {//The ball hits the right boundary, the abscissa speed becomes negative this.speedX = -this.speedX; } if (this.x < 0) {//The ball hits the left boundary, and the abscissa speed becomes positive this.speedX = Math.abs(this.speedX); } if (this.y > canvas.height - this.r * 2) { //When the ball hits the lower boundary, the ordinate speed becomes negative this.speedY = -this.speedY; } if (this.y < 0) {//When the ball hits the upper boundary, the ordinate speed becomes positive this .speedY = Math.abs(this.speedY); } ctx.drawImage(this.img, this.x, this.y, 60, 60);//Draw the ball}}
The main purpose is to add a motion function to the prototype of the gashapon object. The function of the motion function is to make the gashapon move according to its speed and rebound when it touches the boundary.
initializationThe next step is to put the gashapon in the gashapon machine:
function init() {//Initialization for (let i = 0; i < ballNum; i++) {//Randomly generate balls of various colors let index = Math.floor(4 * Math.random()); awardList[i] = new Ball(index, ballList[index]);//New ball object} window.clearInterval(timer);//Clear timer timer = setInterval(function () { ctx.clearRect(0, 0, canvas.width, canvas.height);//Clear the canvas for (let i = 0; i < awardList.length; i++) { awardList[i].run(); }//Make the ball move}, 15); }
In this way, there are already small balls in the gashapon machine.
Start gachaThe main process of starting the gashapon is to click the button. The gashapon machine will reduce the number of gashapon eggs and obtain the corresponding gashapon eggs. The winning display will be:
function play() { if (awardList.length === 0) {//There is no ball in the prize pool alert('Start again!'); init(); message.innerText = 'Click to draw'; } else { window. clearInterval(timer);//Clear the timer let r = awardList.pop();//Reduce the balls in the award pool timer = setInterval(function () { ctx.clearRect(0, 0, canvas.width, canvas.height);//Clear the canvas for (let i = 0; i < awardList.length; i++) { awardList[i].run(); }//Make the ball move}, 15); switch (r.color) {//ball dropping animation 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 () { //The gashapon is successful and prompts award.setAttribute('class', ''); switch (r.color) { case 0: message.innerText = 'Purple ball! '; break; case 1: message.innerText = 'Green ball! '; break; case 2: message.innerText = 'Yellow ball! '; case 3: message.innerText = 'Red ball! '; break; } , 1100); }}
The falling animation of the gashapon here is completed using the key frames of CSS animation:
.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); }}Finish
Of course, you need to add init(); at the end to make the gashapon machine run. At this point, this simple gashapon machine is completed, and the effect is previewed.
SummarizeAlthough this Demo is relatively simple, there are still some points to note and some areas that can be optimized.
Note
img object
These img tags in html:
<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>
The style is also written as display: none;. This is written to obtain the img object in js. Of course, you can also write these img tags directly in the js file without writing them in html:
var img = new Image(); img.src = 'img/1.png';
In this way, you can also get the img object and can also be used to draw gashapon.
clear timerThe timer is cleared in the code before the timer is called. The purpose of this is because if the timer is not cleared, the timer will keep counting, causing the animation to become more and more weird.
canvasWhen drawing on the canvas, the image may be unclear or enlarged. This situation can be solved by setting the width and height attributes of the canvas tag to be the same as the width and height attributes of the style.
The above is the entire content of this article. I hope it will be helpful to everyone’s study. I also hope everyone will support VeVb Wulin Network.