我想做的就是在缓冲区上绘制我的图形,然后能够像画布一样复制它,以便我可以做动画并避免闪烁。但是我找不到这个选项。有人知道我该怎么做吗?

有帮助吗?

解决方案

以下有用的链接,除了显示使用双重缓冲的示例和优势外,还显示了使用HTML5帆布元素的其他一些性能提示。它包括指向JSPERF测试的链接,这些链接将跨浏览器的测试结果汇总到浏览器数据库中。这样可以确保验证性能技巧。

http://www.html5rocks.com/en/tutorials/canvas/performance/

为了方便起见,我提供了一个最小的有效双重缓冲的例子,如本文所述。

// canvas element in DOM
var canvas1 = document.getElementById('canvas1');
var context1 = canvas1.getContext('2d');

// buffer canvas
var canvas2 = document.createElement('canvas');
canvas2.width = 150;
canvas2.height = 150;
var context2 = canvas2.getContext('2d');

// create something on the canvas
context2.beginPath();
context2.moveTo(10,10);
context2.lineTo(10,30);
context2.stroke();

//render the buffered canvas onto the original canvas element
context1.drawImage(canvas2, 0, 0);

其他提示

一种非常简单的方法是在同一屏幕位置有两个帆布元素,并设置需要显示的缓冲区的可见性。完成后,请在隐藏并翻转。

一些代码:

CSS:

canvas { border: 2px solid #000; position:absolute; top:0;left:0; 
visibility: hidden; }

在JS中翻转:

Buffers[1-DrawingBuffer].style.visibility='hidden';
Buffers[DrawingBuffer].style.visibility='visible';

DrawingBuffer=1-DrawingBuffer;

在此代码中,数组“ buffers []'持有两个帆布对象。因此,当您想开始绘画时,您仍然需要获取上下文:

var context = Buffers[DrawingBuffer].getContext('2d');

浏览器,我已经测试了所有处理此缓冲的方法,直到绘制框架的代码完成的代码为止。另请参阅Whatwg邮件列表: http://www.mail-archive.com/whatwg@lists.whatwg.org/msg19969.html

你总是可以做var canvas2 = document.createElement("canvas");并且根本不将其附加到DOM。

只是说,因为你们似乎很着迷 display:none;对我来说,这似乎更干净,模仿双重缓冲的想法,而不是只有一个笨拙的看不见的画布。

两年多后:

无需“手动”实施双重缓冲。 Geary先生在他的书中写了这一点 “ HTML5画布”.

有效减少闪烁的使用 requestAnimationFrame()!

乔什(Josh)(前一段时间)询问了浏览器如何知道“何时结束”以避免闪烁。我会直接对他的帖子发表评论,但我的代表还不够高。这只是我的看法。我没有事实来支持它,但是我对此感到非常自信,这可能对其他人在将来阅读这篇文章有帮助。

我猜想完成绘图后,浏览器不知道。但是,就像大多数JavaScript一样,只要您的代码运行而不将控件放在浏览器中,浏览器就可以实质上锁定,并且不会/不能/无法更新/响应其UI。我猜想,如果您清除画布并绘制整个框架而不将控制权放在浏览器上,那么直到完成后,它实际上不会绘制画布。

如果您设置了渲染范围跨越多个settimeout/setInterval/requestAnimationframe呼叫的情况,则在接下来的几个呼叫中清除画布并在画布上绘制元素,例如每5个呼叫,i 'd愿意打赌您会看到闪烁,因为每次通话后都会更新画布。

就是说,我不确定我会相信。在执行之前,我们已经将JavaScript汇编为本机机器代码(至少这是Chrome的V8引擎从我的理解中所做的)。如果不久之后,浏览器开始在与UI的单独线程中运行其JavaScript并同步对UI元素的任何访问允许UI在无法访问UI的JavaScript执行过程中更新/响应,我不会感到惊讶。当/如果发生这种情况时(我知道有许多障碍必须克服某种双打。

就个人而言,我喜欢两个画布元素相互放置并交替的想法,这些元素在每个框架上显示/绘制。相当不受欢迎,并且很可能很容易地添加到现有的应用程序中,并使用几行代码添加。

对于不信者,这里有一些闪烁的代码。请注意,我明确清除以删除上一个圆圈。

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

function draw_ball(ball) {
    ctx.clearRect(0, 0, 400, 400);
    ctx.fillStyle = "#FF0000";
    ctx.beginPath();
    ctx.arc(ball.x, ball.y, 30, 0, Math.PI * 2, true);
    ctx.closePath();
    ctx.fill();
}

var deltat = 1;
var ball = {};
ball.y = 0;
ball.x = 200;
ball.vy = 0;
ball.vx = 10;
ball.ay = 9.8;
ball.ax = 0.1;

function compute_position() {
    if (ball.y > 370 && ball.vy > 0) {
        ball.vy = -ball.vy * 84 / 86;
    }
    if (ball.x < 30) {
        ball.vx = -ball.vx;
        ball.ax = -ball.ax;
    } else if (ball.x > 370) {
        ball.vx = -ball.vx;
        ball.ax = -ball.ax;
    }
    ball.ax = ball.ax / 2;
    ball.vx = ball.vx * 185 / 186;
    ball.y = ball.y + ball.vy * deltat + ball.ay * deltat * deltat / 2
    ball.x = ball.x + ball.vx * deltat + ball.ax * deltat * deltat / 2
    ball.vy = ball.vy + ball.ay * deltat
    ball.vx = ball.vx + ball.ax * deltat
    draw_ball(ball);
}

setInterval(compute_position, 40);
<!DOCTYPE html>
<html>
<head><title>Basketball</title></head>
<body>
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
</body></html>

网络浏览器没有闪烁!他们已经使用DBL缓冲进行渲染。 JS引擎将在显示之前制作所有渲染。另外,上下文保存和还原仅堆栈变换矩阵数据等,而不是帆布内容本身。因此,您不需要或不需要DBL缓冲!

与其滚动自己的行动,您可能会通过使用现有库来创建清洁和无闪烁的JavaScript动画来获得最佳的里程:

这是一个受欢迎的: http://processingjs.org

您需要2个画布:(注意CSS Z索引和位置:绝对)

<canvas id="layer1" width="760" height="600" style=" position:absolute; top:0;left:0; 
visibility: visible;  z-index: 0; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>
<canvas id="layer2" width="760" height="600" style="position:absolute; top:0;left:0; 
visibility: visible;  z-index: 1; solid #c3c3c3;">
Your browser does not support the canvas element.
</canvas>

您可以注意到,第一个画布是可见的,第二个帆布隐藏在隐藏的想法之后,我们将隐藏可见的,并使隐藏的帆布可见。当它隐藏时'透明隐藏的画布

<script type="text/javascript">
var buff=new Array(2);
buff[0]=document.getElementById("layer1");
buff[1]=document.getElementById("layer2");

ctx[0]=buff[0].getContext("2d");
ctx[1]=buff[1].getContext("2d");
var current=0;
// draw the canvas (ctx[ current ]);
buff[1- current ].style.visibility='hidden';
buff[ current ].style.visibility='visible';
ctx[1-current].clearRect(0,0,760,600);
current =1-current;

Opera 9.10非常慢,显示了绘图过程。如果您想查看浏览器不使用双重缓冲,请尝试Opera 9.10 Out。

有人建议浏览器以某种方式确定绘图过程何时结束,但是您能解释一下如何工作吗?我还没有注意到Firefox,Chrome或IE9的任何明显闪烁,即使图纸很慢,因此似乎他们在做的事情,但是如何完成这是一个谜。浏览器将如何知道在执行更多绘图说明之前,它正在刷新显示器?您是否认为它们只是时间的时间,因此,如果不执行画布绘图指令的间隔超过5ms左右,则假设它可以安全地交换缓冲区?

在大多数情况下,您无需这样做,浏览器会为您实施。 但并不总是有用的!

当您的图纸非常复杂时,您仍然必须实现此目标。大多数屏幕更新速率约为60Hz,这意味着每16ms的屏幕更新。浏览器的更新速率可能接近此数字。如果您的形状需要100ms才能完成,您会看到未完成的形状。因此,您可以在这种情况下实施双重缓冲。

我已经进行了测试: Clear a rect, wait for some time, then fill with some color. 如果我将时间设置为10ms,我不会闪烁。但是,如果我将其设置为20ms,则会发生闪烁。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top