HTML canvas双缓冲帧率问题 [英] HTML canvas double buffering frame-rate issues

查看:289
本文介绍了HTML canvas双缓冲帧率问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个全屏幕画布上绘制了3张图片。当我调整窗口大小时,这些图像改变位置;但是,它似乎是非常毛刺,在Firefox中更是如此。

I have a full-screen canvas with 3 images drawn on it. When I resize the window, these images change position; however, it appears to be very glitchy, more so in Firefox.

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

I've been reading that double-buffering should resolve this issue, but I'm wondering how I would double buffer when the next position is unknown. That is to say, I cannot determine what should be buffered in the future, so how would this be possible?

这里是一个似乎可行的源,但我不充分理解Fedor正在试图解释的概念。

Here is one source that seems doable, but I do not fully understand the concept Fedor is trying to explain.

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;
    c.x = x;
    c.y = 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);
    };
}


推荐答案

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

I think maybe you are misunderstanding what double buffering is. Its a technique for smooth real-time rendering of graphics on a display.

这个概念是你有两个缓冲区。在任何时间只有一个可见。当你去绘制组成一个框架的元素,你将它们绘制到不可见的缓冲区。在你的情况下云。然后你翻转缓冲区使隐藏的可见和可见的一个隐藏。然后在下一帧,你绘制到现在新隐藏的缓冲区。

The concept is you have two buffers. Only one is visible at any one time. When you go to draw the elements that make up a frame you draw them to the invisible buffer. In you case the clouds. Then you flip the buffers making the hidden one visible and the visible one hidden. Then on the next frame you draw to the now newly hidden buffer. Then at the end of drawing you flip back.

这样做会阻止用户在框架完成之前看到元素的局部渲染。在游戏系统上,这也将与显示器的垂直刷新同步以真正平滑并且停止诸如撕裂发生的伪像。

What this does is stop the user seeing partial rendering of elements before a frame is complete. On gaming systems this would also be synced up with the vertical refresh of the display to be really smooth and stop artefacts such as tearing to occur.

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

Looking at you code above you seem to have created the two canvas elements, but you're only using the first Context object. I assume this is incomplete as no flipping is taking place.

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

Its also worth noting that the window resize event can fire continuously when dragging which can cause frantic rendering. I usually create a timer on the resize event to actually re-render. This way the re-render only happens once the user stops resizing for a few milliseconds.

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

Also, your draw routine is creating new Image objects every time which you don't need to do. You can use one image object and render to the canvas multiple times. This will speed up your render considerably.

希望这有助于。

这篇关于HTML canvas双缓冲帧率问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆