使用 toBlob 下载画布 API 生成的图像

对于Purple11,这是我与Gatsby一起构建的一项副项目,我创建了一个简单的云结构生成器(https://purple11.com/cloud-texture-generator/),它使用SVG过滤器和Canvas API在帽子底下。

为了让用户将生成的纹理下载到他们的机器作为Jpeg文件,内线SVG(使用过滤器)首先需要画在面料对象上,因为不幸的是,没有办法直接从内线SVG图形生成可下载的文件。

<$>[注] 如果您对 Canvas API 一般来说是新手,并且想获得概述,请查看本文(https://andsky.com/tech/tutorials/js-drawing-shapes-canvas-api)。

内置 SVG 到 Canvas

首先,你要使用DOM方法来选择你的内线SVG元素,说我们的SVG有一个idmy-svg:

1const mySVG = document.getElementById('my-svg');

然后你会使用 XMLSerializer对 SVG 的内容进行序列化,并使用 btoa(二进制到ascii)创建它的 base64 版本:

1const xml = new XMLSerializer().serializeToString(mySVG);
2const svg64 = btoa(xml);

然后你可以直接从 base64 编码的字符串生成可下载的文件,但我面临的问题是,大多数浏览器对这样的 base64 编码的字符串的尺寸施加限制以作为文件下载。

创建一个新的 HTML 图像元素,并将其src属性设置为我们的 SVG 的 base64 版本:

1const image = new Image();
2const b64Start = 'data:image/svg+xml;base64,';
3image.src = b64Start + svg64;

现在,我们在页面上有一个实际的HTML图像元素,其中包含我们SVG的镜像,我们可以将其绘制到Canvas 2D背景中。

首先,我们需要创建一个 Canvas 2D 背景,以我们的图像大小。假设您已经在页面上有idmy-canvas的面板元素:

1const canvas = document.getElementById('my-canvas');
2const ctx = canvas.getContext('2d');
3ctx.fillStyle = 'white';
4ctx.fillRect(0, 0, image.naturalWidth, image.naturalHeight);

我们可以听到我们创建的图像元素上的上载事件,以便实际上将其绘制到我们的面具背景对象上:

1image.onload = () => {
2  ctx.drawImage(image, 0, 0, image.naturalWidth, image.naturalHeight);
3};

好吧,所以现在有了所有这些 shenanigans,我们终于把我们的内线SVG结果拉进了面具对象中,我们可以转到有趣的部分,实际上可以通过 canvas 的 toBlob方法生成一个可下载的文件。

使用 toBlob 创建可下载的 JPEG 或 PNG 图像

正如它的名字所暗示的那样,toBlob 方法将画布图像转化为blob. Blob 是一个字符串的二进制表示,然后可以在您的机器上下载作为文件。

toBlob首先采用回调函数作为参数,它接收了blob本身,并在回调中您可以继续使用blob做任何您想要的操作。 toBlob还可以使用2个额外的参数,即模仿类型(默认为图片/png)和质量,预计0(0%质量)和1(100%质量)之间的数字,当使用像image/jpeg这样的丢失模仿类型时会变得有用。

例如,这将创建 90% 的质量的 Jpeg Blob:

1canvas.toBlob(
2  blob => {
3    // do something with the blob here...
4  },
5  'image/jpeg',
6  0.9,
7);

创建 创建 创建

我们可以做的就是使用 URL.createObjectURL创建从现在的内存块的 URL。

我们可以简单地在页面上选择一个标签,并将其href属性设置为URL:

1canvas.toBlob(
2  blob => {
3    const anchor = document.getElementById('download-link');
4    anchor.href = URL.createObjectURL(blob);
5  },
6  'image/jpeg',
7  0.9,
8);

然后,用户只需要点击子来启动文件下载。


但是我们可以做得更好,并且自动启动文件下载,所以我们会使用一个小技巧(LINK0),在那里我们会编程地创建一个元素(a),并编程地点击它来自动触发下载:

 1canvas.toBlob(
 2  blob => {
 3    const anchor = document.createElement('a');
 4    anchor.download = 'my-file-name.jpg'; // optional, but you can give the file a name
 5    anchor.href = URL.createObjectURL(blob);
 6
 7    anchor.click(); // ✨ magic!
 8
 9    URL.revokeObjectURL(anchor.href); // remove it from memory and save on memory! 😎
10  },
11  'image/jpeg',
12  0.9,
13);

您还会注意到,通过我们的自动下载图像,我们可以从内存中释放/清理生成的blob到URL地图,因为blob现在已经被下载为机器上的文件,所以我们已经完成了。

包装上

这可能看起来像是围绕着获得我们所需要的东西而拼搏,但这是你会做的一种设置,然后回到专注于你喜欢的裤子应用程序的实际功能上。

Published At
Categories with 技术
Tagged with
comments powered by Disqus