[英]how to fix the bliking of the balls in the canvas?
使用新的構造函數ball(color)創建ball的對象類型。 它的屬性包括將其繪制在畫布上並使他沿隨機方向移動的所有條件。 當創建一個球orangeBall = new ball('orange')時,它將很好地顯示出來,包括其在畫布上的運動。 但是,當添加另一個時,它們都開始閃爍。 如何解決呢? 謝謝。
<!DOCTYPE html>
<html lang="he">
<head>
<meta charset="utf-8" />
<title>
כדורים קופצים רנדומלית בצבעים שונים
</title>
<style>
html,body {
margin: 0;
padding: 0;
background: black;
}
.container { width:900px; margin:0 auto; }
#canvas { background:#8613eb; border:1px solid #cbcbcb; }
</style>
<script>
var ctx;
var H = 800;
var W = 800;
window.onload = function () {
ctx = canvas.getContext("2d");
canvas.width=W;
canvas.height=H;
function ball(color) {
//life - the amount of time to show the ball in the screen
this.life = 60*1000, //1 minute
this.color = arguments.length==1 ? color: 'white';
this.x= Math.round(Math.random()*W);
this.y= Math.round(Math.random()*H);
this.radius= 10 + Math.round(Math.random()*50);// between 10-60
this.dx=1+ Math.round(Math.random()*5); //between 1-6
this.dy= 2+ Math.round(Math.random()*4); //between 2-6
this.startAngel= 0;
this.endAngel= 2*Math.PI; //360deg
this.speed= 3+Math.round(Math.random()*50) //3-50msec
this.show = function() {
//first clear the previous ball
ctx.clearRect(0,0,canvas.width,canvas.height);
var xClear = (this.x-this.radius) <=0 ? 0:(this.x - this.radius);
var yClear = (this.y-2*this.radius) <=0 ? 0:(this.y - 2*this.radius);
ctx.clearRect(xClear,yClear,canvas.width,canvas.height);
//lets stroke the ball
ctx.beginPath();
ctx.fillStyle = this.color;
this.x+=this.dx;
this.y+=this.dy;
if (this.x<0 || this.x>W) {
this.dx=-this.dx;
}
if (this.y<0 || this.y>H) {
this.dy=-this.dy;
}
ctx.arc(this.x,this.y,this.radius,this.startAngel,this.endAngel);
ctx.closePath();
ctx.fill();
this.life-=this.speed;
var _this = this;
// creating new property in the ball 'timePointer'
this.timePointer = this.life<=0 ?
clearInterval(this.timePointer):
setTimeout(function() {
_this.show();
},this.speed);
}
this.show();
};
orangeBall = new ball('orange');
blackBall = new ball('black');
// whiteBall = new ball('white');
// yellowgeBall = new ball('yellow');
// pinkBall = new ball('pink');
// blueBall = new ball('blue');
// greenBall = new ball('green');
};
</script>
</head>
<body>
<div class="container">
<canvas id="canvas">Your browser doesn't support this game.</canvas>
</div>
</body>
</html>
每個球通過其show
功能繪制自身之后,您正在清理整個畫布。 不必讓球離開畫布,而是要有一個間隔,該間隔將調用一個函數,該函數將清除畫布一次,然后迭代所有球並繪制它們。
動畫分為幀。 一幀大約是1/60秒,並且在那一刻繪制了所有動畫。
為了幫助制作動畫,瀏覽器提供了一個函數,您可以使用該函數來調用渲染幀的函數。 requestAnimationFrame(yourfunction)
requestAnimationFrame
會告訴瀏覽器您正在對動畫進行更改。 這將停止將畫布呈現給顯示器,直到刷新下一個垂直顯示器為止。
使用setInterval
或setTimeout
function animateSomething(){
// draw something
} // as soon as this exits the content of the canvas is moved to the display
// there is no way to know where the display hardware is writing pixels to
// display, could be halfway through drawing a ball
setInterval(animateSomething,1000 / 60);
如果每次退出時對許多對象執行此操作,則像素將移至顯示器,而與顯示器硬件的工作無關。 這導致閃爍,剪切和其他問題。
使用requestAnimationFrame
function animateSomething(){
// draw something
requestAnimationFrame(animateSomething)
} // The content of the canvas does not move to the display until the
// display hardware is getting ready to scan the next display refresh
requestAnimationFrame(animateSomething);
處理動畫的最佳方法是從一個功能進行所有渲染。
下面我修改了您的代碼以使用requestAnimationFrame
消除閃爍,我添加了一個mainLoop
函數來繪制所有球。 我讓瀏覽器處理時間。
var ctx; var H = 800; var W = 800; window.onload = function() { ctx = canvas.getContext("2d"); canvas.width = W; canvas.height = H; function ball(color) { //life - the amount of time to show the ball in the screen this.life = 60 * 1000; //1 minute this.color = arguments.length == 1 ? color : 'white'; this.x = Math.round(Math.random() * W); this.y = Math.round(Math.random() * H); this.radius = 10 + Math.round(Math.random() * 50); // between 10-60 this.dx = 1 + Math.round(Math.random() * 5); //between 1-6 this.dy = 2 + Math.round(Math.random() * 4); //between 2-6 this.startAngel = 0; this.endAngel = 2 * Math.PI; //360deg this.speed = 3 + Math.round(Math.random() * 50) //3-50msec this.show = function() { //first clear the previous ball ctx.beginPath(); ctx.fillStyle = this.color; this.x += this.dx; this.y += this.dy; if (this.x < 0 || this.x > W) { this.dx = -this.dx; } if (this.y < 0 || this.y > H) { this.dy = -this.dy; } ctx.arc(this.x, this.y, this.radius, this.startAngel, this.endAngel); ctx.closePath(); ctx.fill(); this.life -= this.speed; } }; orangeBall = new ball('orange'); blackBall = new ball('black'); whiteBall = new ball('white'); yellowgeBall = new ball('yellow'); pinkBall = new ball('pink'); blueBall = new ball('blue'); greenBall = new ball('green'); var balls = [orangeBall, blackBall, whiteBall, yellowgeBall, pinkBall, blueBall, greenBall]; function mainLoop(){ ctx.clearRect(0, 0, canvas.width, canvas.height); for(var i = 0; i < balls.length; i++){ if(balls[i].life > 0){ balls[i].show(); } } requestAnimationFrame(mainLoop); } requestAnimationFrame(mainLoop); };
html, body { margin: 0; padding: 0; background: black; } .container { width: 900px; margin: 0 auto; } #canvas { background: #8613eb; border: 1px solid #cbcbcb; }
<div class="container"> <canvas id="canvas">Your browser doesn't support this game.</canvas> </div>
我更改了代碼以使用原型。 那個更好嗎 ? 此外,它還不夠平滑。 還添加了性能時間表以幫助您。
var ctx; var H = window.innerHeight; var W = window.innerWidth; window.onload = function () { ctx = canvas.getContext("2d"); canvas.width=W; canvas.height=H; function ball(color) { //life - the amount of time to show the ball in the screen this.life = 60*10, //duration of 600 X 16ms(fram per sec) this.color = arguments.length==1 ? color: 'white'; this.x= Math.round(Math.random()*W); this.y= Math.round(Math.random()*H); this.radius= 10 + Math.round(Math.random()*50);// between 10-60 this.dx=1+ Math.round(Math.random()*5); //between 1-6 this.dy= 2+ Math.round(Math.random()*4); //between 2-6 this.startAngel= 0; this.endAngel= 2*Math.PI; //360deg this.start = null; }; ball.prototype.show = function() { //lets stroke the ball ctx.beginPath(); ctx.fillStyle = this.color; this.x+=this.dx; this.y+=this.dy; if (this.x<0 || this.x>W) { this.dx=-this.dx; } if (this.y<0 || this.y>H) { this.dy=-this.dy; } ctx.arc(this.x,this.y,this.radius,this.startAngel,this.endAngel); ctx.closePath(); ctx.fill(); this.life--; }; var arrBalls = [] ; arrBalls.push(new ball('orange')); arrBalls.push(new ball('black')); arrBalls.push(new ball('white')); arrBalls.push(new ball('pink')); arrBalls.push(new ball('blue')); arrBalls.push(new ball('green')); // This loop shell be less then 10ms inorder not to maintain // 60fps interval of screen hardware rendering var balldeth = 0; function paint() { //clear the canvas once in xframes ctx.clearRect(0,0,canvas.width,canvas.height); //paint balls in the canvas for (var i = 0; i < arrBalls.length; i++ ) { arrBalls[i].life >= 0 ? arrBalls[i].show() : ++balldeth; } (balldeth == arrBalls.length) ? console.log("game over"):window.requestAnimationFrame(paint); } window.requestAnimationFrame(paint); };
html,body { margin: 0; padding: 0; background: black; } #canvas { background:#8613eb; border:1px solid #cbcbcb; }
<body> <canvas id="canvas">Your browser doesn't support this game.</canvas> </body>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.