如何将 canvas blob 存储到数组?

How can I store canvas blob to an array?

我想使用 canvas.toBlob 函数将 canvas 元素中的几个 blob 存储到一个数组中。

我试过下面的代码,但没有用。结果显示 .toBlob() 函数像 async 函数一样工作,我对此一无所知。

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);

结果:

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]

我的最终目标是收集几个 canvas 元素,然后将它们合并到一个 PDF 文件中(在用户脚本中)。但是,我发现我无法制作 PDF,所以我决定使用 Node.js.

然后,我决定更进一步:下载 PNG 并要求用户使用另一个 Python 脚本将它们合并为 PDF 文件。这就是为什么我需要一个包含这些 blob 的 zip。

The result showed that the toBlob function seems like an async function, and I have no knowledge about it.

是的,toBlob() 接受回调,您现在正在代码中使用它。但是,我们可以使用 async、await 和 Promises 轻松清理它。我会在同一个循环中完成这一切。未经测试的代码,但尝试这样的事情:

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;
}

By the way, my final goal is to collect several canvas elements then merge them to a pdf file (In a user script).

您是否考虑过用于创建 PDF 客户端的各种 JavaScript 库之一?例如,jsPDF:https://github.com/parallax/jsPDF

我发现 canvas.toDataURL 帮助很大。

/**
 * 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");
    });
}