如何解决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,canvasWidth,canvasHeight);
context.closePath();
bgImg = new Image();
bgImg.src = \"images/bg.png\";
bgImg.onload = function()
{
context.drawImage(bgImg,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,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,elt){
elt.draw();
elt.enddraw();
});
self.inDOM();
}
(...)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。