使用rect()和fillRect()进行画布优化

时间:2013-08-18 21:15:29

标签: javascript performance optimization canvas drawing

我正在尝试绘制一个n×n的正方形网格,其中每个正方形由彼此叠加的颜色层组成。使用fillRect()将颜色绘制到画布上似乎工作正常,而不会消耗任何资源。但是,当我尝试使用rect()在每个方块周围添加边框时,性能会明显下降。

在每次调用下面的函数之前,我使用clearRect()来清除画布。

有问题的功能:

/**
 * Draws an n x n grid of layered color squares of the given width.
 * @param {int} `width`      The width of each square in the grid.
 * @param {int} `leftOffSet` The left margin of the grid.
 * @param {int} `topOffSet`  The top margin of the grid.
 * @param {int} `n`          The dimension of the grid.
 * @param {object} `layers'  A linked-list of color layers.
 */
function drawMap(width, leftOffSet, topOffSet, n, layers) {
    for (var i = 0; i < n; i++) {
        for (var j = 0; j < n; j++) {

            var currentLayer = layers[i][j];
            while (typeof currentLayer.tile !== 'undefined') {
                var bg = currentLayer.tile.background;

                context.fillStyle = 'rgba(' + bg.r + ',' + bg.g + ',' + bg.b + ',' + bg.a + ')';
                context.fillRect(i * width + leftOffSet, j * width + topOffSet, width, width);

                currentLayer = currentLayer.next;
            }

            // BOTTLE NECK APPEARS TO BE HERE
            /*context.beginPath();
            context.rect(i * width + leftOffSet, j * width + topOffSet, width, width);
            context.stroke();
            context.closePath();*/

        }
    }
}

随着瓶颈的注释,性能很好,但是一旦我取消注释该块,性能就会下降。有没有办法优化这个?

1 个答案:

答案 0 :(得分:1)

将context.stroke放在循环之外

在定义时不需要描绘每个单独的矩形 - 只需在最后一次触发context.stroke。

function drawMap(width, leftOffSet, topOffSet, n, layers) {

    // begin a new path
    context.beginPath();

    for (var i = 0; i < n; i++) {
        for (var j = 0; j < n; j++) {

            var currentLayer = layers[i][j];
            while (typeof currentLayer.tile !== 'undefined') {
                var bg = currentLayer.tile.background;

                context.fillStyle = 'rgba(' + bg.r + ',' + bg.g + ',' + bg.b + ',' + bg.a + ')';
                context.fillRect(i * width + leftOffSet, j * width + topOffSet, width, width);

                currentLayer = currentLayer.next;
            }

            // define new rects,
            //  but don't stroke every new rect
            context.rect(i * width + leftOffSet, j * width + topOffSet, width, width);

            // closePath is not needed if you're just rect-ing
            // context.closePath();


        }
    }

    // all done defining rects, now just do 1 stroke that draws them all
    context.stroke();

}