咱們須要使用到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。