咱们须要使用到Canvas的方法有:javascript
context.arc(x, y, r, sAngle, eAngle, counterclockwise);
var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), w = canvas.width, //canvas画布的宽 h = canvas.height,// canvas画布的高 posX = 20,//定义圆心X坐标 posY = 20,//定义圆心Y坐标 radius = 20;//定义半径 ctx.clearRect(0, 0, w, h);//清除画布 ctx.beginPath();//开始绘制 ctx.arc(posX,posY,radius,0,2*Math.PI);//画圆 ctx.fillStyle = 'red';//圆的填充颜色 ctx.closePath();//闭合路径 ctx.fill();//填充
在线预览:https://codepen.io/jianxiujiu...java
让小球动起来的原理就是,不断地改变小球的坐标位置并进行重绘。
重绘能够用setInterval、setTimeout或requestanimationframe。关于它们的区别此处不作详解,具体能够参考我好基友的一篇文章:setTimeout 和 requestAnimationFrameweb
window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, posX = 20, //小球出现的X轴位置 posY = 20, //小球出现的Y轴位置 speedX = 3,//小球X轴速度 speedY = 3,//小球Y轴速度 radius = 20;//小球半径 function ani(){ ctx.clearRect(0, 0, canvas.width, canvas.height); posX += speedX; posY += speedY; ctx.beginPath(); ctx.arc(posX,posY,radius,0,2*Math.PI); ctx.fillStyle = 'red'; ctx.closePath(); ctx.fill(); if(posY < h - radius){ requestAnimFrame(ani) //若是Y轴位置不超过容器高度则一直移动 } } ani();
在线预览:https://codepen.io/jianxiujiu...canvas
接下来咱们让小球动起来,并在画布四周进行碰撞运动。数组
window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, posX = 20, posY = 20, speedX = 2,//小球X轴速度 speedY = 2,//小球Y轴速度 startSpeedX = 2,//小球X轴初始速度 startSpeedY = 2,//小球Y轴初始速度 radius = 20;//小球半径 function ani(){ ctx.clearRect(0, 0, canvas.width, canvas.height); posX += speedX; posY += speedY; //小球碰壁反弹 if(posY > h - radius){ speedY*=-1; } if(posX > w - radius){ speedX*=-1; } if(posY < radius){ speedY = startSpeedY; posY = radius; } if(posX < radius){ speedX = startSpeedX; posX = radius; } ctx.beginPath(); ctx.arc(posX,posY,radius,0,2*Math.PI); ctx.fillStyle = 'red'; ctx.closePath(); ctx.fill(); requestAnimFrame(ani); } ani();
在线预览:https://codepen.io/jianxiujiu...dom
window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, posX, posY, speedX, speedY, radius; function randomNum(m,n) { //随机函数 return Math.floor(Math.random() * (n - m + 1) + m); } var balls = [] //创建小球数组 function getBall(){ for( n = 0; n < 20;n++){ //小球的数量 radius = randomNum (10,20), //半径随机10-20px posX = randomNum(radius,w-radius), //X轴位置随机 posY = randomNum(radius,h-radius), //Y轴位置随机 speedX = randomNum(3,6), //X轴速度随机 speedY = randomNum(1,2), //Y轴速度随机 startSpeedX = startSpeedX,//记录X轴起始速度 startSpeedY = startSpeedY;//记录X轴起始速度 fillColor = 'rgb(' + randomNum(0,255) + ',' + randomNum(0,255) + ',' + randomNum(0,255) + ')';//小球颜色随机 var ball = { radius : radius, posX : posX, posY : posY, speedX : speedX, speedY : speedY, startSpeedX : startSpeedX, startSpeedY : startSpeedX, fillColor : fillColor } balls.push(ball) //将生成的小球存到数组里 } } getBall(); function draw(){ ctx.clearRect(0, 0, canvas.width, canvas.height); var l = balls.length; for(var i = 0;i<l;i++){ //逐一绘制小球动画 ctx.beginPath(); ballCur = balls[i]; ballCur.posX += ballCur.speedX; ballCur.posY += ballCur.speedY; if(ballCur.posY > h - ballCur.radius){ ballCur.speedY*=-1; } if(ballCur.posX > w - ballCur.radius){ ballCur.speedX*=-1; } if(ballCur.posY < ballCur.radius){ ballCur.speedY = startSpeedY; ballCur.posY = ballCur.radius; } if(ballCur.posX < ballCur.radius){ ballCur.speedX = startSpeedX; ballCur.posX = ballCur.radius; } ctx.arc(ballCur.posX,ballCur.posY,ballCur.radius,0,2*Math.PI); ctx.fillStyle = ballCur.fillColor; ctx.closePath(); ctx.fill(); } requestAnimFrame(draw); } draw();
在线预览:https://codepen.io/jianxiujiu...函数
小球动起来以后,若是但愿小球为图片,则须要用到Canvas另一个方法:动画
context.drawImage(image, x, y); //在画布上定位图像: context.drawImage(image, x, y, width, height);//在画布上定位图像,并规定图像的宽度和高度 context.drawImage(image, sourceX, sourceY, sourceWidth, sourceHeight,destX, destY, destWidth, destHeight);//剪切图像,并在画布上定位被剪切的部分
和绘制普通小球不同,绘制图片球的时候,咱们须要把以前动画的代码在加载完图片以后再执行。而且碰撞的位置也须要进行调整。rest
window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(callback){ window.setTimeout(callback, 1000 / 60); }; })(); var canvas = document.getElementById('canvas'), ctx = canvas.getContext('2d'), w = canvas.width, h = canvas.height, ballWidth = 60, //图片球宽度 posX, posY, speedX, speedY; var img = new Image(); img.src = 'img/ball.png'; img.onload = function(){ getBall(); draw(); } function randomNum(m,n) { return Math.floor(Math.random() * (n - m + 1) + m); } var balls = [] function getBall(){ for( n = 0; n < 20;n++){ posX = randomNum(ballWidth,w - ballWidth), posY = randomNum(ballWidth,h - ballWidth), speedX = randomNum(3,7), speedY = randomNum(4,8), startSpeedX = speedX, startSpeedY = speedY; ballPicPos = randomNum(0,4)*60; //小球图片位置随机 var ball = { posX : posX, posY : posY, speedX : speedX, speedY : speedY, startSpeedX : startSpeedX, startSpeedY : startSpeedX, ballPicPos : ballPicPos } balls.push(ball); } } function draw(){ ctx.clearRect(0, 0, canvas.width, canvas.height); var l = balls.length; for(var i = 0;i<l;i++){ ballCur = balls[i]; ballCur.posX += ballCur.speedX; ballCur.posY += ballCur.speedY; if(ballCur.posY > h - ballWidth){ ballCur.speedY*=-1; } if(ballCur.posX > w - ballWidth){ ballCur.speedX*=-1; } if(ballCur.posY < 0){ ballCur.speedY = startSpeedY; ballCur.posY = 0; } if(ballCur.posX < 0){ ballCur.speedX = startSpeedX; ballCur.posX = 0; } ctx.beginPath(); ctx.fillStyle = ctx.drawImage(img,0,ballCur.ballPicPos,ballWidth,ballWidth,ballCur.posX,ballCur.posY,ballWidth,ballWidth); ctx.fill(); ctx.closePath(); ctx.restore(); } requestAnimFrame(draw); }
线上预览:https://codepen.io/jianxiujiu...code
PS:小球的图片位置若是取值大于图片自己的位置,则IE11下显示图片会有BUG。