Quiero almacenar varios blobs de elementos de canvas usando la función canvas.toBlob en una matriz.
Probé el siguiente código que fue inútil. El resultado mostró que la función .toBlob() funciona como una función async y no tengo conocimiento al respecto.
function saveAllPics(node_list) { // convert canvas element to png let pics = []; for (let canvas of node_list) { canvas.toBlob(function(blob) { pics.push(blob); console.log(pics); }); } let zipPics = function(pics) { // compress all pics into a zip file let zip = new JSZip(); console.log("pics length:", pics.length); for (let i = 0; i < pics.length; i++) { let pic_data = pics[i]; console.log(i); console.log(pic_data); zip.file("pic-" + String(i) + ".png", pic_data, { binary: true }); } console.log(zip); } setTimeout(function(pics) { zipPics(pics); }, 2000);Y el resultado:
pics length: 0 {files: {…}, comment: null, root: '', clone: ƒ} [Blob] (2) [Blob, Blob] (3) [Blob, Blob, Blob] (4) [Blob, Blob, Blob, Blob] (5) [Blob, Blob, Blob, Blob, Blob] (6) [Blob, Blob, Blob, Blob, Blob, Blob] (7) [Blob, Blob, Blob, Blob, Blob, Blob, Blob] (8) [Blob, Blob, Blob, Blob, Blob, Blob, Blob, Blob]Mi objetivo final es recopilar varios elementos del lienzo y luego fusionarlos en un archivo PDF (en un script de usuario). Sin embargo, descubrí que no podía hacer un PDF, así que decidí usar Node.js.
Luego, decidí ir un paso más allá: descargue los PNG y pida a los usuarios que usen otro script de Python para fusionarlos en un archivo PDF. Es por eso que necesito un zip que contenga estos blobs.
El resultado mostró que la función toBlob parece una función asíncrona y no tengo conocimiento al respecto.
Sí, toBlob() acepta una devolución de llamada y ahora la estás usando en tu código. Pero podemos limpiar esto fácilmente usando async, await y Promises. Haría todo esto en el mismo ciclo. Código no probado, pero prueba algo como esto:
async function saveAllPics(canvases) { const zip = new JSZip(); for (const [i, canvas] of canvases.entries()) { zip.file( // File name `pic-${i}.png`, // File data await new Promise((resolve, reject) => { // If a blob is returned, success!... otherwise reject. canvas.toBlob(blob => blob ? resolve(blob) : reject()); }), // JSZip Options { binary: true } ); } return zip; }Por cierto, mi objetivo final es recopilar varios elementos del lienzo y luego fusionarlos en un archivo pdf (en un script de usuario).
¿Ha considerado una de las diversas bibliotecas de JavaScript para crear archivos PDF en el lado del cliente? Por ejemplo, jsPDF: https://github.com/parallax/jsPDF
Descubrí que canvas.toDataURL ayudó mucho.
/** * store all canvas imgs as pngs into a zip file * @param {Array} node_list canvas元素列表*/ function saveAllPics(node_list) { let zip = new JSZip(); let n = node_list.length; for (let i = 0; i < n; i++) { let canvas = node_list[i]; let data_base64 = canvas.toDataURL(); let blob = atob(data_base64.split(",")[1]); zip.file(`page-${i}.png`, blob, { binary: true }); } // promise.then(onCompleted, onRejected); zip.generateAsync({ type: "blob" }).then(function(content) { // see filesaver.js console.log(content); saveAs(content, "pics.zip"); }); }