Проблемы с двойной частотой кадров в буфере HTML - PullRequest
2 голосов
/ 27 декабря 2010

У меня полноэкранный холст с 3 нарисованными изображениями. Когда я изменяю размер окна, эти изображения меняют положение; тем не менее, он выглядит очень глючно, особенно в Firefox.

Я читал, что двойная буферизация должна решить эту проблему, но мне интересно, как бы я удвоил буфер, когда следующая позиция неизвестна То есть я не могу определить, что следует буферизовать в будущем, так как это будет возможно?

Вот один источник, который кажется выполнимым, но я не совсем понимаю концепцию, которую Федор пытается объяснить.

Поддерживает ли 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);
    };
}

1 Ответ

8 голосов
/ 28 февраля 2011

Я думаю, может быть, вы неправильно понимаете, что такое двойная буферизация.Это техника плавного рендеринга графики в реальном времени на дисплее.

Идея в том, что у вас есть два буфера.Только один виден одновременно.Когда вы начинаете рисовать элементы, которые составляют рамку, вы рисуете их в невидимый буфер.В твоем случае облака.Затем вы переворачиваете буферы, делая скрытый видимым, а видимый скрытым.Затем в следующем кадре вы рисуете в недавно скрытый буфер.Затем в конце рисунка вы переворачиваете назад.

Что это делает, это останавливает пользователя, видящего частичную визуализацию элементов до завершения кадра.В игровых системах это также можно синхронизировать с вертикальным обновлением дисплея, чтобы оно было действительно плавным и препятствовало возникновению таких артефактов, как разрыв.

Глядя на код выше, вы, кажется, создали два элемента canvas,но вы используете только первый объект Context.Я предполагаю, что это неполно, так как никакого переворота не происходит.

Стоит также отметить, что событие изменения размера окна может происходить непрерывно при перетаскивании, что может привести к неистовой визуализации.Я обычно создаю таймер для события resize, чтобы фактически перерисовать.Таким образом, повторный рендеринг происходит только после того, как пользователь перестает изменять размер на несколько миллисекунд.

Кроме того, ваша процедура рисования создает новые объекты Image каждый раз, что вам не нужно делать.Вы можете использовать один объект изображения и рендерить на холст несколько раз.Это значительно ускорит ваш рендеринг.

Надеюсь, это поможет.

...