HTML5 Canvas在FireFox 4中闪烁

| 我正在HTML5画布上进行概念验证。在Chrome和IE9中,我能够像魅力一样工作,但是在Firefox 4中,由于重新绘制画布,所以我一直在闪烁。我已经尝试了该站点上提到的一些技术,例如双缓冲,但是仍然出现大量闪烁。任何对此的见解将不胜感激!
<!DOCTYPE HTML>
<html>
<head>
<style type=\"text/css\">  
body
{  
    margin:0px;  
    padding:0px;  
    text-align:center;  
} 
canvas
{  
    outline:0;  
    border:1px solid #000;  
    margin-top: 10px;
    margin-left: auto;  
    margin-right: auto;  
}  
</style>
<script type=\"text/javascript\">
var canvasWidth = 640;
var thisXPos = 0;
var canvasHeight = 820;
var thisYPos = 0;
var canvas = null;
var context = null;
var gLoop = null;
var rain = [];
var rainImg = \"images/raindrop.gif\";
var bgImg = null;
var i;

for (i = 0; i < howManyLetters; i++)
{
    rain.push([Math.floor(Math.random() * canvasWidth), Math.floor(Math.random() * canvasHeight),rainImg]);
}

var DrawRain = function()
{
    for (i = 0; i < 10; i++)
    {
        thisXPos = rain[i][0];
        thisYPos = rain[i][1];
        imgSrc = rain[i][2];
        letterImg = new Image();
        letterImg.setAtX = thisXPos;
        letterImg.setAtY = thisYPos;
        letterImg.onload = function()
        {
            context.drawImage(this, this.setAtX, this.setAtY);
        }
        letterImg.src = imgSrc;
    }
};

var MoveRain = function(e)
{
    for (i = 0; i < 10; i++)
    {
        if ((rain[i][1] - 5) > canvasHeight)
        {
            randomnumber = Math.floor(Math.random()*26);

            rain[i][0] = Math.random() * canvasWidth;
            rain[i][1] = 0;
            rain[i][2] = rainImg;
        }
        else
        {
            rain[i][1] += e;
        }
    }
};

var clear = function()
{
    context.beginPath();
    context.rect(0, 0, canvasWidth, canvasHeight);
    context.closePath();

    bgImg = new Image();
    bgImg.src = \"images/bg.png\";
    bgImg.onload = function()
    {
        context.drawImage(bgImg,0,0);
    }
} 

var GameLoop = function()
{
    context.save();
    clear();
    MoveRain(1);
    DrawRain();
    context.restore();

    gLoop = setTimeout(GameLoop, 10);
}

function loadGame()
{
    canvas = document.getElementById(\"gameCanvas\");
    context = canvas.getContext(\"2d\");
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;

    GameLoop();
}

</script>
</head>
<body onload=\"loadGame();\">
    <canvas id=\"gameCanvas\"></canvas>
</body>
</html>
    
已邀请:
我将您的示例简化为: http://jsfiddle.net/sPm3b/6/ 而且它在Firefox和Chrome中运行非常快。 因此我们知道问题出在图像上。 您需要优化它们的创建和加载方式。现在,每个
clear()
都会创建一个新图像并等待其加载!该图像只应在ѭ2中创建一次,然后反复使用。 与
DrawRain()
中的with3ѭ相同。将其创建移至
loadGame()
那可能会解决问题。 编辑: 像这样: 在顶部添加:
var letterImg = new Image();
var bgImg = new Image();
然后
function loadGame()
{
    canvas = document.getElementById(\"gameCanvas\");
    context = canvas.getContext(\"2d\");
    canvas.width = canvasWidth;
    canvas.height = canvasHeight;

    bgImg.src = \"images/bg.png\";
    letterImg.src = \"images/raindrop.gif\";

    // optional: wait for them to load here

    GameLoop();
}
然后,例如drawRain如下所示:
var DrawRain = function()
{
    for (i = 0; i < 10; i++)
    {
        thisXPos = rain[i][0];
        thisYPos = rain[i][1];
        context.drawImage(letterImg, thisXPosX, thisYPos); // letterImg was already constructed, no need to make it again
    }
};
    
补充西蒙·萨里斯的回应。我使用了“双画布”技术来避免在较厚的画布上晃动屏幕。 它的工作方式始终是使用画布的2个版本,一个在DOM中,一个在外部,并始终在非DOM中使用。我将其与重绘队列一起使用。 这是工作代码的一部分
(...)
clear: function() {
    //rotating on 2 canvas, one for draw (outside DOM) one for show
    var self = this;
    if (null == self.canvasbackup) {
        var tmpcanvas = self.canvas.clone(true);
        self.canvasbackup = self.canvas;
        self.canvas=tmpcanvas;
    } else {
        var tmpcanvas = self.canvasbackup;
        self.canvasbackup = self.canvas;
        self.canvas=tmpcanvas;
    }
    self.ctx = self.canvas[0].getContext(\'2d\');
    self.ctx.clearRect( 0, 0, self.options.width, self.options.height );
    jQuery.each(self.elements,function(idx,elt){
        // custom function: my elements need to know which canvas they depends on
        elt.reconnectCanvas(self.canvas,self.ctx);
    });
},
inDOM: function() {
    var self = this;
    if(null==self.canvasbackup) {
        //1st time need to get all things in DOM
        self.canvas.appendTo(self.div);
        self.div.appendTo(self.container);
    } else {
        // remove current shown canvas
        self.connectHuman();
        self.canvasbackup.remove();
        // loosing some events here...
        self.canvas.appendTo(self.div);
        // div is already in DOM, we are in redraw
    }
},
redraw: function() {
    var self = this;
    self.clear();
    jQuery.each(self.elements,function(idx,elt){
        elt.draw();
        elt.enddraw();
    });
    self.inDOM();
}
(...)
    

要回复问题请先登录注册