如何有效地更新数百个元素的动态绘制背景

时间:2015-05-14 23:52:04

标签: javascript canvas

所以,我的表格在其单元格上有动态绘制的背景,并且会定期更新。这个表可以有数百行,因此效率非常重要。

我目前的解决方案是将背景绘制到画布上,然后通过数据URI将此图形用作单元格上的背景图像。

cell.css({backgroundImage:'url(' + canvas.toDataURL('image/png')+ ')' });

这样做没问题,但是html源代码变得非常大,编码图像中的所有重复内容都会变得很大,最终会让一些浏览器挣扎。

有没有办法以某种方式重复使用相同的数据URI而不重复它?

我考虑过的其他想法: - 直接使用canvas元素作为-webkit-canvas-moz-element的背景,但这似乎与Internet Explorer不兼容。 - 绝对在每个单元格中放置画布并重新绘制内容,但是当我们达到数百行时,这并不是非常有效。

2 个答案:

答案 0 :(得分:1)

选项1:

使用Canvas2Blob

基本上,您可以通过调用URL.createObjectURL(blob);来获取网址字符串,其中blob是从polyfill返回的对象canvas.toBlob(function (blob) {...});

这样做的好处是,由于编码,Blob的大小是dataURI字符串的3/4,并且在使用100次时不应该是内存/处理器密集型。

选项2:

如果你真的想使用canvas.toDataURL('image/png');,那么将它存储到像

这样的字符串变量中
var str = canvas.toDataURL('image/png');
// ...
cell.css({backgroundImage:'url(' + str + ')' });

根据浏览器的实现,调用.toDataURL()可能是一个非常昂贵的函数调用,并且因为所有单元格需要相同的背景,所以最好只将它存储到字符串中。

答案 1 :(得分:1)

  

有没有办法以某种方式重用相同的数据URI而不重复它?

不,数据URI只是二进制数据的文本表示,这里是生成的PNG(或JPEG)文件。如果您需要更改内容,则必须首先更改二进制数据,然后根据该数据对URI进行编码。因此无法重复使用。

.nohistory {margin-top: 20px;} 也是一个非常缓慢的过程,使用这种技术还涉及每次构建,编码,压缩,解析,解压缩和解码位图数据,这在编码/解码文件之上并从Base-64表示。

  

如何有效地更新数百个元素的动态绘制背景

以下是我要做的事情:

  • 使用放置在桌子后面且尺寸相同的单个画布元素(使用CSS进行放置,但测量画布大小的像素宽度/高度)。
  • 创建一个迭代表格单元格以查找其像素大小的函数,最初使用一次,每次调整浏览器大小。
  • 将矩形直接渲染到画布元素

实施例



<footer class="nohistory columns" style="margin-top: 20px;">
&#13;
toDataURL()
&#13;
var table = document.querySelector("table"),
    canvas = document.querySelector("canvas"),
    ctx = canvas.getContext("2d");

getArray();  // and on resize if needed

function getArray() {
  // todo: iterate table here to find sizes for each cell.
  // For simplicity just the table width and height is measured in this example:
  var rect = table.getBoundingClientRect();
  canvas.width = rect.width;
  canvas.height = rect.height;
}

// render for demo -
(function loop() {
  render();
  requestAnimationFrame(loop)
})();

function render() {
  var cw = canvas.width * 0.5,
      ch = canvas.height * 0.5;
  for(var y = 0; y < 2; y++) {
    for(var x = 0; x < 2; x++) {
      ctx.fillStyle = "hsl(" + (360*Math.random()) + ",80%,70%)";
      ctx.fillRect(x * cw, y * ch, cw, ch);
    }
  }
}
&#13;
&#13;
&#13;

图像缓存

另一种方法是使用图像预生成数组并将其源设置为data-uri。

然后直接将图像用作表格的背景。