我怀疑您的示例代码只是一个示例,但以防万一没有更简单的方法来用单一颜色填充区域:
ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, 500, 500);
但回到展平阵列。如果性能是一个因素,您可以通过以下方式进行:
(旁注:如果可能的话 - 将颜色信息直接存储在您想要使用的相同类型和字节顺序中,因为当您处理数十个字符时,从字符串转换为数字可能会相对昂贵数千像素 - 二进制/数字存储也更便宜)。
直接将二维数组展开/展平为类型化数组:
var width = 500, height = 500;
var data32 = new Uint32Array(width * height); // create Uint32 view + underlying ArrayBuffer
for(var x, y = 0, p = 0; y < height; y++) { // outer loop represents rows
for(x = 0; x < width; x++) { // inner loop represents columns
data32[p++] = str2uint32(array[x][y]); // p = position in the 1D typed array
}
}
我们还需要将颜色的字符串表示法转换为 little-endian 顺序的数字(目前大多数消费类 CPU 使用的格式)。 Shift、AND 和 OR 操作比处理字符串部分快几倍,但如果你可以完全避免字符串,那将是理想的方法:
// str must be "#RRGGBB" with no alpha.
function str2uint32(str) {
var n = ("0x" + str.substr(1))|0; // to integer number
return 0xff000000 | // alpha (first byte)
(n << 16) | // blue (from last to second byte)
(n & 0xff00) | // green (keep position but mask)
(n >>> 16) // red (from first to last byte)
}
在这里,我们首先将字符串转换为数字 - 我们立即将其转换为 Uint32 值以优化编译器,现在我们知道我们打算在接下来的转换中将数字用作整数。
由于我们很可能在一个小端平台上,我们必须在字节周围移动、屏蔽和 OR 以得到正确的字节顺序(即 0xAABBGGRR)和 OR 在 alpha 通道中作为不透明的结果数字(在大-endian 平台,您只需将整个值左移 8 位,然后在最后的 alpha 通道中进行 OR)。
然后最后使用我们刚刚填充的底层ArrayBuffer 创建一个ImageData 对象,并给它一个Uint8ClampedArray 需要ImageData 的视图(这几乎没有开销,因为底层ArrayBuffer 是共享的):
var idata = new ImageData(new Uint8ClampedArray(data32.buffer), width, height);
从这里你可以使用context.putImageData(idata, x, y)。
示例
这里用橙色填充以使转换可见(如果您得到的颜色与橙色不同,那么您在大端平台上:)):
var width = 500, height = 500;
var data32 = new Uint32Array(width * height);
var screen = [];
// Fill with orange color
for(var x = 0; x < width; x++ ){
screen[x] = [];
for(var y = 0; y < height; y++ ){
screen[x][y] = "#ff7700"; // orange to check final byte-order
}
}
// Flatten array
for(var x, y = 0, p = 0; y < height; y++){
for(x = 0; x < width; x++) {
data32[p++] = str2uint32(screen[x][y]);
}
}
function str2uint32(str) {
var n = ("0x" + str.substr(1))|0;
return 0xff000000 | (n << 16) | (n & 0xff00) | (n >>> 16)
}
var idata = new ImageData(new Uint8ClampedArray(data32.buffer), width, height);
c.getContext("2d").putImageData(idata, 0, 0);
<canvas id=c width=500 height=500></canvas>