HTML canvas双缓冲帧率问题

我有一个全屏canvas,上面画有3张图片。 当我调整窗口大小时,这些图像会改变位置; 然而,它似乎非常小问题,在Firefox中更是如此。

我一直在读,双缓冲应该解决这个问题,但我想知道如果下一个位置未知,我将如何双缓冲。 也就是说,我无法确定将来应该缓存什么,那么这怎么可能呢?

这是一个看似可行的来源,但我并不完全理解Fedor试图解释的概念。

HTML5 / Canvas是否支持双缓冲?

到目前为止,我有,

$canvas = $('#myclouds')[0]; $canvas_buffer = $('canvas')[0].insertAfter($canvas).css('visibility', 'hidden'); context = $canvas.getContext('2d'); context_buffer = $canvas_buffer.getContext('2d'); clouds_arr = [$canvas, $canvas_buffer]; $(window).resize(function () { drawCanvas(); }; function initCanvas() { // Sources for cloud images var cloud1 = '/js/application/home/images/cloud1.png', cloud2 = '/js/application/home/images/cloud2.png', cloud3 = '/js/application/home/images/cloud3.png'; // add clouds to be drawn // parameters are as follows: // image source, x, y, ratio, adjustment) addCloud(cloud1, null, 125, .03); addCloud(cloud2, null, 75, .15); addCloud(cloud3, null, 50, .55); addCloud(cloud1, null, 125, .97, 300); addCloud(cloud2, null, 70, .85, 300); addCloud(cloud3, null, 45, .5, 300); // Draw the canvas drawCanvas(); } function drawCanvas() { // Reset $canvas.attr('height', $window.height()).attr('width', $window.width()); // draw the clouds var l = clouds.length; for (var i = 0; i < l; i++) { clouds[i].x = ($window.width() * clouds[i].ratio) - clouds[i].offset; drawimage(context, clouds[i]); } } function Cloud() { this.x = 0; this.y = 0; } function addCloud(path, x, y, ratio, offset) { var c = new Cloud; cx = x; cy = y; c.path = path; c.ratio = ratio || 0; c.offset = offset || 0; clouds.push(c); } function drawimage(ctx, image) { var clouds_obj = new Image(); clouds_obj.src = image.path; clouds_obj.onload = function() { ctx.drawImage(clouds_obj, image.x, image.y); }; } 

我想也许你误解了双缓冲是什么。 它是一种在显示器上平滑实时渲染图形的技术。

这个概念是你有两个缓冲区。 任何时候只能看到一个。 当你去绘制构成一个框架的元素时,你将它们绘制到不可见的缓冲区。 在你的情况下云。 然后你翻转缓冲区使隐藏的一个可见,隐藏可见的缓冲区。 然后在下一帧上绘制到现在新隐藏的缓冲区。 然后在绘图结束时你回头。

这样做是为了阻止用户在帧完成之前看到元素的部分渲染。 在游戏系统上,这也将与显示器的垂直刷新同步,以实现非常平滑并且停止诸如撕裂之类的伪像。

看看上面的代码,你似乎已经创建了两个canvas元素,但是你只使用了第一个Context对象。 我认为这是不完整的,因为没有发生翻转。

值得注意的是,窗口resize事件可以在拖动时连续触发,这可能导致疯狂渲染。 我通常在resize事件上创建一个计时器来实际重新渲染。 这样,只有在用户停止resize几毫秒后才会重新呈现。

此外,您的绘图例程每次都不需要创建新的Image对象。 您可以使用一个图像对象并多次渲染到canvas。 这将大大加快渲染速度。

希望这可以帮助。