【问题标题】:How to wait for the multiple images to load in the canvas and convert to base64?如何等待多个图像加载到画布中并转换为 base64?
【发布时间】:2017-12-03 20:02:21
【问题描述】:

我正在尝试在 HTML5 中获取 base64 版本的画布。

目前,我从画布上得到的 base64 图像是空白的。

我发现了类似的问题,例如这个:

HTML Canvas image to Base64 problem

但是,我遇到的问题是,因为我在画布中添加了 2 个图像,所以我不能使用这些答案中提供的示例,因为它们中的大多数都使用单个图像。

我知道在尝试获取 base64 图像之前,我必须等到画布图像正确加载。但我不知道我的情况如何。

这是我的代码:

var canvas = document.getElementById('myCanvas');
      var context = canvas.getContext('2d');
  	  context.canvas.width = 1000;
      context.canvas.height = 1000;




var imageObj1 = new Image();

  imageObj1.src = "http://www.offthegridnews.com/wp-content/uploads/2017/01/selfie-psuDOTedu.jpg";
  imageObj1.onload = function() {
    context.drawImage(imageObj1, 0, 180, canvas.width, canvas.height);
  };

var imageObj2 = new Image();


  imageObj2.src = "http://www.publicdomainpictures.net/pictures/150000/velka/banner-header-tapete-145002399028x.jpg"
  imageObj2.onload = function() {
    context.drawImage(imageObj2, 0, 0, canvas.width, 180);
  };
  
// get png data url
//var pngUrl = canvas.toDataURL();
  
var pngUrl = canvas.toDataURL('image/png');

// get jpeg data url 
 var jpegUrl = canvas.toDataURL('image/jpeg');


$('#base').val(pngUrl);
        <div class="contents" style="overflow-x:hidden; overflow-y:scroll;">


            <div style="width:100%; height:90%;">

            <canvas id="myCanvas" class="snap" style="width:100%; height:100%;" onclick="takephoto()"></canvas>


            </div>		
			
        </div>
        
        
        
        <p>
        This is the base64 image
        </p>
        
        <textarea id="base">
        
        
        </textarea>

这是一个有效的 FIDDLE:

https://jsfiddle.net/3p3e6Ldu/1/

有人可以就这个问题提出建议吗?

提前致谢。

编辑:

按照下面 cmets 的建议,我尝试使用计数器,当计数器达到特定数字时,我将画布转换为 base64。

像这样:https://jsfiddle.net/3p3e6Ldu/4/

【问题讨论】:

  • 您可以在每次加载图像时使用计数器,当所有图像都加载完毕时,您可以执行代码以获取 base64 数据。
  • @MrZach,我试过了。但我不能让它工作:jsfiddle.net/3p3e6Ldu/3
  • 示例中的if( count == 2 ) 部分必须在onload 回调中。你应该熟悉异步编码!
  • @Sirko,我也试过了。它没有用。你试过你的建议了吗?

标签: javascript jquery html canvas


【解决方案1】:

在您的两个示例(来自问题的示例和来自 cmets 的示例)中,命令的顺序并没有真正尊重手头任务的异步性质。 在后面的示例中,您应该将 if( count == 2 ) 块放在 onload 回调中以使其工作。

但是,即使这样,您也会遇到下一个问题:您正在从不同的域加载图像。您仍然可以绘制它们(在画布中或使用&lt;img&gt; 标签),但您无法直接访问它们的内容。即使绕道使用&lt;canvas&gt; 元素也不行。

如果图像托管在同一个域上,我更改了代码以便它可以工作。我还使用了一个函数来加载图像并承诺处理回调。使用回调和计数变量的直接方式对我来说似乎很容易出错。如果您查看相应的fiddle,您会注意到显示的SecurityError。这是我提到的 Same-Origin-Policy 的上述问题的结果。

我的一个previous question 在类似的方向是关于如何检测,如果我在添加一些图像后仍然可以读取&lt;canvas&gt; 的内容。

const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
context.canvas.width = 1000;
context.canvas.height = 1000;

// function to retrieve an image
function loadImage(url) {
  return new Promise((fulfill, reject) => {
    let imageObj = new Image();
    imageObj.onload = () => fulfill(imageObj);
    imageObj.src = url;
  });
}

// get images
Promise.all([
    loadImage("http://www.offthegridnews.com/wp-content/uploads/2017/01/selfie-psuDOTedu.jpg"),
    loadImage("http://www.publicdomainpictures.net/pictures/150000/velka/banner-header-tapete-145002399028x.jpg"),
  ])
  .then((images) => {
    // draw images to canvas
    context.drawImage(images[0], 0, 180, canvas.width, canvas.height);
    context.drawImage(images[1], 0, 0, canvas.width, 180);

    // export to png/jpg
    const pngUrl = canvas.toDataURL('image/png');
    const jpegUrl = canvas.toDataURL('image/jpeg');

    // show in textarea
    $('#base').val(pngUrl);
  })
  .catch( (e) => alert(e) );

【讨论】:

  • 我刚刚阅读了另一个关于这个跨域问题的问题,你发布了这个答案。感谢您澄清一切。
猜你喜欢
  • 1970-01-01
  • 2017-07-19
  • 1970-01-01
  • 2018-06-26
  • 2016-04-30
  • 2019-01-19
  • 2015-06-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多