怎么下载不同的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!!
解除问题评论:
加载图片是异步的,所以callback
是异步调用的。
如果所有 canvas 组合(多张图像的不同集合)在不到一秒内完成,则 setTimeout
对 download
的调用只会看到canvas 处于最终状态。要解决此问题,您可以
- 在创建下一个下载之前等待每个下载启动,或者
- 使用多个 canvas 元素,或者
- 将每个 canvas 组合的数据 URL 存储在一个数组中,以便稍后下载。
如果跨域加载图片,服务器不允许cross domain requests, canvas.toDataURL
throws a security exception。因此无法使用其中提供的 URL 修复 fiddle。
我正在开发一个 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!!
解除问题评论:
加载图片是异步的,所以
callback
是异步调用的。如果所有 canvas 组合(多张图像的不同集合)在不到一秒内完成,则
setTimeout
对download
的调用只会看到canvas 处于最终状态。要解决此问题,您可以- 在创建下一个下载之前等待每个下载启动,或者
- 使用多个 canvas 元素,或者
- 将每个 canvas 组合的数据 URL 存储在一个数组中,以便稍后下载。
如果跨域加载图片,服务器不允许cross domain requests,
canvas.toDataURL
throws a security exception。因此无法使用其中提供的 URL 修复 fiddle。