对于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有一个id
的my-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 背景,以我们的图像大小。假设您已经在页面上有id
的my-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现在已经被下载为机器上的文件,所以我们已经完成了。
包装上
这可能看起来像是围绕着获得我们所需要的东西而拼搏,但这是你会做的一种设置,然后回到专注于你喜欢的裤子应用程序的实际功能上。