怎么下载不同的html canvas画上去呢?

How to download different html canvas after drawing on it?

我正在开发一个 nft-art-generator 应用程序,该应用程序生成多个 differnte html canvas(如图)。 每个canvas是3张图的组合,换句话说,每个canvas要画3张图,画完canvas我就下载了。

问题是当我检查下载的 canvas 时,我得到了相同的 canvas。更准确地说,我得到最后生成的 canvas 已被下载多次,就像之前生成的所有 canvas 都消失了。

我认为这是因为我的代码中的某些内容是 运行 异步的。

这是我的React.js代码

const generateCollection = async()=>{

//In this exemple i want to generate 2 canvas only!!
  for(var k = 1; k <= 2; k++){
    drawLayer(data, k)
   }
  
}
  
const drawLayer = (data, index)=>{
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d')
  let sources = {};
  //Get some random images url
  const objURLs = getImagesURLs(data, index);
  
  objURLs.forEach((url,i)=>{
    const key = `image${i+1}`;
    Object.assign(sources, {[key]: url})
  })
  
  loadImages(sources, function(images) {
    objURLs.forEach((url,i)=>{
      if (Boolean(url)) {
        context.drawImage(images[`image${i+1}`], 0, 0, 230, 230)
      }
    })
  });
  
  setTimeout(()=> download(canvas.current, index), 1000);
  
}

const loadImages = (sources, callback)=> {
  var images = {};
  var loadedImages = 0;
  var numImages = 0;
  // get num of sources
  for(var src in sources) {
    numImages++;
  }
  for(var src in sources) {
    images[src] = new Image();
    images[src].onload = function() {
      if(++loadedImages >= numImages) {
        console.log("!!  ", images )
          callback(images);
      }
    };
    images[src].src = sources[src];
  }
}

const download = (canvas, index)=>{
  console.log("Download: ", canvas)
  var url = canvas.toDataURL("image/png");
  var link = document.createElement('a');
  link.download = `img_${index}.png`;
  link.href = url;
  link.click();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<canvas 
  id="myCanvas"
  ref={canvas}
  width={230}
  height={230}
/>

<Button onClick={()=>generateCollection()} ><Button>

这是一个基于

的现场演示代码

https://jsfiddle.net/vprdhomf/1/

I will appreciate any help, or suggestion!!

解除问题评论:

  1. 加载图片是异步的,所以callback是异步调用的。

  2. 如果所有 canvas 组合(多张图像的不同集合)在不到一秒内完成,则 setTimeoutdownload 的调用只会看到canvas 处于最终状态。要解决此问题,您可以

    • 在创建下一个下载之前等待每个下载启动,或者
    • 使用多个 canvas 元素,或者
    • 将每个 canvas 组合的数据 URL 存储在一个数组中,以便稍后下载。
  3. 如果跨域加载图片,服务器不允许cross domain requests, canvas.toDataURL throws a security exception。因此无法使用其中提供的 URL 修复 fiddle。