首页 > 解决方案 > 提高精灵绘制性能

问题描述

我有这个函数来绘制一个精灵对象(它只是一个具有像素值数组的对象):

this.draw = (ctx, x, y, scale) => {
    let i = 0;
    let startIndex, red, green, blue, alpha, currentX, currentY;
    while(i < this.size.width * this.size.height){
        startIndex = i * 4;
        red = this.pixArray[startIndex];
        green = this.pixArray[startIndex + 1];
        blue = this.pixArray[startIndex + 2];
        alpha = this.pixArray[startIndex + 3];
        // Draw, but not if the pixel is invisible
        if(alpha != 0){
            ctx.fillStyle = `rgba(${red}, " + ${green} + ", " + ${blue} + ", " + ${alpha / 255.0} + ")`;
            currentX = i % this.size.width;
            currentY = (i - currentX) / this.size.width;
            ctx.fillRect(Math.round(x + (currentX * scale)), Math.round(y + (currentY * scale)),
            Math.round(scale), Math.round(scale));
        }
        i++;
    }
}

唯一缺少的是pixArray,它是一个像素值的 Uint8Array。

但是,性能相当糟糕。我发现画布更改状态 ( ctx.fillStyle) 会丢失一些性能,但有必要每次迭代都修改它。即使 fillStyle 保持不变,性能仍然无法接受。我意识到我可以选择或预渲染,但我希望避免这种情况。

标签: javascriptperformancecanvas

解决方案


使用 anImageData将您的数组直接传送到临时画布,然后在一次操作中以适当的比例将其绘制到目标画布:

const { width, height } = this.size;
const tCan = document.createElement('canvas');

// block scope to clean up temporary variables
{
  const tCtx = tCan.getContext('2d');
  const imgData = tCtx.createImageData(width, height);

  tCan.width = width;
  tCan.height = height;
  imgData.data.set(this.pixArray);
  tCtx.putImageData(imgData, 0, 0);
}

this.draw = (ctx, x, y, scale) => {
  ctx.drawImage(tCan, x, y, Math.round(width * scale), Math.round(height * scale));
};

推荐阅读