canvas toblob_使用toBlob下载Canvas API生成的图像

本文介绍了如何使用Canvas的toBlob方法将内联SVG转换为画布,并创建可下载的JPEG或PNG图像。首先,通过XMLSerializer和btoa将SVG转换为base64,然后在画布上绘制。接着,利用toBlob方法将画布内容转换为blob,最后通过URL.createObjectURL创建下载链接,实现自动下载。
摘要由CSDN通过智能技术生成

canvas toblob

For Purple11, a side project of mine built with Gatsby, I created a simple cloud texture generator that uses SVG filters and the Canvas API under the hood. The SVG filter part allowed me to easily create the cloud texture effect itself, thanks in great part to the feTurbulence filter, but I’ll keep the fascinating topic of SVG filters for another article.

对于使用Gatsby构建的我的副项目Purple11,我创建了一个简单的云纹理生成器,该生成器使用SVG滤镜和引擎盖下的Canvas API。 SVG过滤器部分使我能够轻松地创建云纹理效果本身,这在很大程度上要归功于feTurbulence过滤器,但是我将在另一篇文章中保留SVG过滤器的迷人主题。

In order to let a user download the generated texture to their machine as a Jpeg file, the inline SVG (with filters applied) first needs to be drawn on a canvas object, because unfortunately there’s no way to generate a downloadable file directly from an inline SVG graphic. Obviously, you can skip the whole SVG to Canvas part directly to the meat of the matter if you’re here just to know how to download an image that’s been drawn directly using the Canvas API with toBlob.

为了让用户将生成的纹理作为Jpeg文件下载到他们的机器,首先需要在画布对象上绘制内联SVG(已应用滤镜),因为遗憾的是无法直接从内联生成可下载文件SVG图形。 显然,如果您只是在这里只是想知道如何下载使用Canvas API和toBlob直接绘制的图像,则可以直接将整个SVG到Canvas的部分跳过。

If you’re new to the Canvas API in general and would like to get an overview, check out this article.

如果您是Canvas API的新手,并且想要获得概述, 请查看本文

内联SVG到画布 (Inline SVG to Canvas)

First, you’ll want to use a DOM method to select your inline SVG element. Say our SVG has an id of my-svg:

首先,您将要使用DOM方法来选择嵌入式SVG元素。 假设我们的SVG的idmy-svg

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

And then you’d use XMLSerializer to serialize the content of the SVG and btoa (binary to ascii) to create a base64 version of it:

然后,您将使用XMLSerializer序列化SVG和btoa的内容(二进制到ascii)以创建它的base64版本:

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

You could then generate a downloadable file straight from the base64-encoded string, but the problem I faced is that most browsers impose a limit on the size of such base64-encoded string to be downloaded as a file. So I had to pile on from that point to go around that limitation.

然后,您可以直接从base64编码的字符串生成可下载的文件,但是我面临的问题是,大多数浏览器对要作为文件下载的这种base64编码的字符串的大小施加了限制。 因此,我不得不从那一点开始克服这一限制。

Create a new HTML Image element and set its src property to the base64 version of our SVG:

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

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

And now that we have an actual HTML image element on the page with a mirror image of our SVG, we can draw it onto a Canvas 2D context.

现在,我们在页面上有了一个实际HTML图像元素,并带有SVG的镜像,我们可以将其绘制到Canvas 2D上下文中。

First, we need to create a Canvas 2D context to the size of our image. Assuming that you already have a canvas element on the page with an id of my-canvas:

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

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

And we can listen to the onload event on the image element we’ve created to actually draw it on the our canvas context object:

我们可以在创建的图像元素上监听onload事件,以将其实际绘制在画布上下文对象上:

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


Alright, so now with all of those shenanigans in place we finally have our inline-SVG result drawn into a canvas object. We can move on to the fun part and actually generate a downloadable file, thanks to canvas’ toBlob method.

好吧,现在所有这些恶作剧都就位了,我们终于将内联SVG结果绘制到了画布对象中。 由于canvas的toBlob方法,我们可以继续进行有趣的部分并实际生成可下载的文件。

使用toBlob创建可下载的JPEG或PNG图像 (Creating a Downloadable JPEG or PNG Image using toBlob)

As it’s name implies, the toBlob method turns a canvas-drawn image into a blob. A blob is a binary representation of a string, which can then be downloaded as a file on your machine.

顾名思义, toBlob方法将画布绘制的图像转换为blob。 Blob是字符串的二进制表示形式,可以将其作为文件下载到您的计算机上。

toBlob first takes a callback function as argument, which receives the blob itself, and in the callback you can proceed with doing whatever you’d like with the blob. toBlob can also 2 additional arguments, the mime type (defaults to image/png) and the quality, which expects a number between 0 (0% quality) and 1 (100% quality) that becomes useful when using a lossy mime type like image/jpeg.

toBlob首先将回调函数作为参数,该函数接收blob本身,并且在回调中,您可以继续执行对blob的任何操作。 toBlob还可以添加2个附加参数,即mime类型(默认为image/png )和quality(质量),该参数期望0(0%质量)和1(100%质量)之间的数字在使用有损mime类型(例如image/jpeg )时非常有用image/jpeg

For example, this will create a Jpeg blob at 90% quality:

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

canvas.toBlob(
  blob => {
    // do something with the blob here...
  },
  'image/jpeg',
  0.9,
);

URL.createObjectURL (URL.createObjectURL)

What we can do is create an URL from the now in-memory blob using URL.createObjectURL.

我们可以做的是使用URL.createObjectURL从现在的内存Blob中创建一个URL。

We could just select an anchor tag on the page and set its href attribute to the URL:

我们可以在页面上选择一个锚标记并将其href属性设置为URL:

canvas.toBlob(
  blob => {
    const anchor = document.getElementById('download-link');
    anchor.href = URL.createObjectURL(blob);
  },
  'image/jpeg',
  0.9,
);

Then the user would just have to click on the anchor to initiate the file download.

然后,用户只需单击锚点即可启动文件下载。



But we can do better and have the file download start automatically, so we’ll use a little trick where we programmatically create an anchor element (a), and programmatically click on it to automagically trigger the download:

但是我们可以做得更好,并且可以自动开始文件下载,因此,我们将使用一个小技巧 ,以编程方式创建锚元素( a ),并以编程方式单击它以自动触发下载:

canvas.toBlob(
  blob => {
    const anchor = document.createElement('a');
    anchor.download = 'my-file-name.jpg'; // optional, but you can give the file a name
    anchor.href = URL.createObjectURL(blob);

    anchor.click(); // ✨ magic!

    URL.revokeObjectURL(anchor.href); // remove it from memory and save on memory! 😎
  },
  'image/jpeg',
  0.9,
);

You’ll notice too that with our auto-downloaded image we can release/clean-up the generated blob to URL mapping from memory because the blob has now been downloaded as a file on the machine so we are done with it.

您还将注意到,使用自动下载的图像,我们可以从内存中释放/清理生成的Blob到URL的映射,因为Blob现在已经作为文件下载到了计算机上,因此我们已经完成了。

结语 (Wrapping Up)

This might seem like a lot of juggling around to get what we need, but this is the kind of setup you’d do once and then get back to focusing on the actual features of your fancy pants app. Plus, once what we want saved is drawn into a canvas context, the toBlob method makes it quite easy to allow a file to be saved in whatever format and quality fits the needs of your app best.

为了获得我们所需要的东西,这看起来似乎很费劲,但这是您一次要做的设置,然后又回到专注于花哨的裤子应用程序的实际功能上。 另外,一旦将要保存的内容绘制到画布上下文中, toBlob方法就可以非常轻松地允许以最适合您应用程序需求的格式和质量保存文件。

翻译自: https://www.digitalocean.com/community/tutorials/js-canvas-toblob

canvas toblob

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值