简体   繁体   English

HTMLF Canvas在FireFox 4中闪烁

[英]HTML5 Canvas flicker in FireFox 4

I'm working on a proof of concept on an HTML5 canvas. 我正在HTML5画布上进行概念验证。 I was able to get this working like a charm in Chrome and IE9, but in Firefox 4 I'm getting constant flicker as it redraws the canvas. 我能够像Chrome和IE9中的魅力一样工作,但在Firefox 4中,我在重绘画布时会不断闪烁。 I've tried a few techniques mentioned on this site like double buffering but I'm still getting a large amount of flicker. 我尝试过这个网站上提到的一些技术,比如双缓冲,但我仍然会得到大量的闪烁。 Any insight on this would be appreciated! 任何有关这方面的见解将不胜感激!

<!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>

I have distilled your example down to this: 我把你的例子简化为:

http://jsfiddle.net/sPm3b/6/ http://jsfiddle.net/sPm3b/6/

And it works very fast in Firefox and Chrome. 它在Firefox和Chrome中的运行速度非常快。

So we know that the problem lies in the images. 所以我们知道问题在于图像。

You need to optimize how they are created and loaded. 您需要优化它们的创建和加载方式。 Right now, each clear() creates a new image and waits for it to load! 现在,每个clear()都会创建一个新图像并等待它加载! That image should be created only once, in your loadGame() and then reused over and over. 该图像应该只在loadGame()创建一次,然后反复重复使用。

Same exact deal with letterImg in DrawRain() . 完全相同的处理letterImgDrawRain() Move the creation of it to loadGame() 将其创建移至loadGame()

That will probably fix the problem. 这可能会解决问题。

EDIT: 编辑:

like this: 像这样:

At the top add: 在顶部添加:

var letterImg = new Image();
var bgImg = new Image();

Then 然后

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();
}

Then drawRain, for example, would look like this: 然后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
    }
};

In complement to Simon Sarris response. 作为Simon Sarris回应的补充。 I've used a 'double canvas' technique to avoid screen fickering with heavy canvas. 我使用了“双帆布”技术来避免使用厚帆布进行屏幕争吵。

The way it works is always have 2 version of the canvas, one in DOM, one outside, and always draw on the one which is not in DOM . 它的工作方式总是有2个版本的画布,一个在DOM中,一个在外面,并且总是在不在DOM中的那个上绘制 I use it with a redraw queue. 我用它来重绘队列。

here's a part of a working code 这是工作代码的一部分

(...)
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();
}
(...)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM