canvas无法在循环中生成所有图像

时间:2016-02-23 15:11:30

标签: javascript html5 html5-canvas

我正在使用一个循环来生成一些HTML表,它们不是太大,在循环中我正在执行一些JS(我已经尝试过JQuery和JavaScript)来创建表作为图像。它只是一个35个表的小循环,但通过它的大约三分之二只返回空白图像。我想知道这是一个内存问题还是DOM是不完整的问题所以我把我的语句包装在$(document).ready()仍然是同样的问题。我在循环中使用了其中一个人,他们生成了很好的。我在控制台中没有错误。我一直在控制台中手动执行JQuery并检查生成。

html2canvas($('#kimberly-t'), {
    onrendered: function (canvas) {
        var data = canvas.toDataURL('image/png');
        $('#kimberly-t-canvas').html('<img src="'+data+'" alt="">');
        }
    });

对于每个人,他们都工作正常,然后一个只是不起作用,并且每次后续尝试从新的HTML表创建图像失败。因为没有错误,我甚至不知道如何开始

更新赏金

这是展示问题的fiddle。你可以看到对div的前10个调用生成一个图像。如果取消注释JS的其余部分,它将生成空白画布或使浏览器崩溃。当浏览器没有崩溃时,我从PHP循环或控制台获取本地机器上的错误。

3 个答案:

答案 0 :(得分:1)

我能够通过一些技巧得到它,这里是jsfiddle:https://jsfiddle.net/ksdyeytg/12/

诀窍在于我导出了带有100ms延迟的cavas图像,并将它们存储在一个base64Images数组中,然后在10s延迟显示它们之后

存储部分

setTimeout(function(index){

      html2canvas( $('#div'+index) , {
            onrendered: function(canvas) {
              var data = canvas.toDataURL('image/png');

              // Instead displauing images directly
              //$('#div'+index+'-canvas').html('<img src="' + data + '" alt="">');          
              // Storing images
              base64Images.push( {'index':index, 'data':data} );
            }
      });  
}, 100*i, i );

显示部分

setTimeout(function(index){

    for( var i = 0; i < base64Images.length; i++){

        $('#div' +base64Images[i]['index']+ '-canvas').html(            
           '<img style="border: 5px solid red;" src="' +base64Images[i]['data']+ '" alt="">'
        );
    }
}, 10000 ); 

这不能正常工作other browsers,如果我将100毫秒的延迟更改为较低的数量,它会在chrome下停止工作也会崩溃,如果我改为直接从第26张表图像开始显示图像在最初的Jonnny的例子中没有显示,所以让我们说这个参数只适用于这个数量的表,其中包含这个精确浏览器和PC的数据量......

我知道这不是100%正常的解决方案,但至少是一些

我对这个问题的看法是,它与某种浏览器js堆栈大小限制有关,它们负责以某种方式使用canvas部分。在这个jsfiddle中还有一个注意事项:https://jsfiddle.net/ksdyeytg/11/当我读同一个html表并直接显示它30次正常工作时它正在工作evan 64次显示但是在64之后它再次开始不显示图像,我也在搜索谷歌一些关于这个领域的限制的文档,但它没用......

此解决方案的主要思想是逐部分显示此类图像,以避免浏览器“某些”缓存泄漏

答案 1 :(得分:1)

实际上我无法在Chrome(稳定和金丝雀)或Firefox上重现您的错误!

除了在一个网站中使用如此多的画布节点之外,我没有看到您的代码存在问题。我的笔记本有16 GB内存和一个花哨的CPU,因此没有问题,但任何普通的计算机可能会遇到你描述的问题。

侧面说明:你可能想开始使用for循环进行重复操作,如我的小提琴版https://jsfiddle.net/ksdyeytg/14/中所见

for(var i=1;i<=39;i++) {
  html2canvas($('#div'+i), {
    onrendered: function(canvas) {
      var data = canvas.toDataURL('image/png');
      $('#div'+i+'-canvas').html('<img src="' + data + '" alt="">');
    }
  });
}

答案 2 :(得分:1)

看起来你的DOM操作会影响html2canvas代码(堆栈问题,搞乱事件,竞争条件,我不知道)。

检查https://jsfiddle.net/ksdyeytg/17/(这不是一个非常漂亮的解决方案,但它可以渲染你的39个表,没有用更多的测试)。

这里我一次看一个表并用html2canvas渲染它并将生成的dataurl保存到辅助数组中然后在处理完所有表之后我显示图像:

  var process_div = function(index) {
    var id = divs_to_process[index];
    //console.log('process_div ' + id);
    html2canvas($(id), {
      onrendered: function(canvas) {
        var data = canvas.toDataURL('image/png');
        //$(id + '-canvas').html('<img src="' + data + '" alt="">');
        imgs.push([id + '-canvas', data]);
        data = undefined;
        setTimeout(process_div_wrapper, 0);
      }
    });
  };
  var i = 0;
  var process_div_wrapper = function() {
    if (i < divs_to_process.length) {
      var id = divs_to_process[i];
      process_div(i);
      ++i;
    } else {
      for (var j = 0; j < imgs.length; ++j) {
        var e = imgs[j];
        //console.log('show img ' + e[0]);
        $(e[0]).html('<img src="' + e[1] + '" alt="">');
      }
      alert('done');
    }
  };
  setTimeout(process_div_wrapper, 1);