Javascript Canvas 一项闪烁

Javascript Canvas one item flickering

我试图让物体在 Canvas 中相互移动,当它们相遇并重叠时,一个应该消失,另一个应该落下。现在我得到了执行此操作的动画,但其中一项在闪烁。

<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>

</head>
<body onload="draw(530,15); draw1(1,15);">
<canvas id="canvas" width="600" height="400"></canvas>
<script>
function draw(x,y){
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    ctx.save();
    ctx.clearRect(x, y, 600, 400);
    ctx.fillStyle = "rgba(0,200,0,1)";
    ctx.fillRect (x, y, 70, 50);
    ctx.restore(); 
    x -= 0.5;
 if(x==300)
 {
    return;
 };
    var loopTimer = setTimeout('draw('+x+','+y+')',5);
 };
 
 function draw1(w,e){
    var canvas = document.getElementById('canvas');
    var ctx = canvas.getContext('2d');
    ctx.save();
    ctx.clearRect(w-1,e-2,600,400);
    ctx.fillStyle = "rgba(0,200,0,1)";
    ctx.fillRect (w, e, 70, 50);
    ctx.restore(); 
    w += 1;
 if(w==265)
 {
 w -= 1;
 e +=2;
 };
    var loopTimer = setTimeout('draw1('+w+','+e+')',10);
};
</script>
</body>  
</html>

已经尝试了两天,但似乎无法正确修复它。提前致谢。

两个绘图函数中ctx.clearReact的前2个参数应该是0:

ctx.clearRect(0, 0, 600, 400);

这意味着您清除了所有 canvas。

你的动画方法很过时(即使用setTimeout)。相反,您应该使用 requestAnimationFrame,如下所示。这将提供平滑、无闪烁的动画。

<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>

</head>
<body onload="requestAnimationFrame(animate);">
<canvas id="canvas" width="600" height="400"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
  
var x = 530, y = 15;  
function animate(){
  requestID = requestAnimationFrame(animate);
  ctx.clearRect(x, y, 600, 400);
  ctx.fillStyle = "rgba(0,200,0,1)";
  ctx.fillRect (x, y, 70, 50);
  x -= 0.5;
  if(x==300)
  {
    cancelAnimationFrame(requestID)
  };
}
</script>
</body>  
</html>

您每秒渲染太多帧,迫使浏览器显示帧。每次绘制函数 returns 时,浏览器都会假定您要将框架呈现给页面。

动画需要与显示刷新率同步,对于大多数设备来说,刷新率是 60FPS。为此,您需要一个处理所有动画的渲染循环。您通过 requestAnimationFrame (RAF) 调用此函数,确保动画与显示硬件和浏览器渲染保持同步。

<!DOCTYPE html>
<html>
<head>
<style>
canvas{border:#666 3px solid;}
</style>

</head>
<!-- dont need this <body onload="draw(530,15); draw1(1,15);">-->
<body>
<canvas id="canvas" width="600" height="400"></canvas>
<script>
var canvas,ctx,x,y,w,e;
var canvas,ctx,x,y,w,e;
function draw() {
    ctx.fillStyle = "rgba(0,200,0,1)";
    ctx.fillRect(x, y, 70, 50);
};

function draw1(w, e) {
    ctx.fillStyle = "rgba(0,200,0,1)";
    ctx.fillRect(w, e, 70, 50);
};

function update(time){  // high precision time passed by RAF when it calls this function
    ctx.clearRect(0,0,canvas.width,canvas.height); // clear all of the canvas
    if(w + 70 >= x){
        e += 2;        
    }else{
        x -= 0.75;
        w += 1;
    };
    draw(x,y);
    draw1(w,e);

    requestAnimationFrame(update)
    // at this point the function exits and the browser presents
    // the canvas bitmap for display
}

function start(){ // set up
    x = 530;
    y = 15;
    w = 1;
    e = 15;
    canvas = document.getElementById('canvas');
    ctx = canvas.getContext('2d');
    requestAnimationFrame(update)
}
window.addEventListener("load",start);
</script>
</body>  
</html>