了解如何轻松地将 SVG 字符串渲染到画布中,然后将其导出为具有所需大小的 PNG 或 JPEG,而不会降低质量,包括具体的SVG字符串渲染到画布实例。
图像的操作总是有点棘手,尤其是当你想使用 JavaScript 等语言进行操作时,如果还不够,可以直接在浏览器中操作。在过去的几天里,我一直在使用一个非常特殊的库,即dom-to-image,该库允许你使用纯 JavaScript 将任意 DOM 节点转换为矢量(SVG)或光栅(PNG 或 JPEG)图像. 我使用这个库来简单地在浏览器中捕获一个 DOM 元素,以允许用户下载图像,就是这样。
从理论上讲,它非常简单,因为 DOM 只是一组带有表情符号的按钮集合,它看起来像这样:
请注意,上图是使用外部工具制作的屏幕截图,并保持原始大小。现在,如果我决定使用 JPEG 或 PNG 中提到的库导出 DOM 元素,它将大大降低质量:
这当然不是库的错,因为它将 DOM 元素光栅化为 PNG 格式的图像,但是,它看起来很糟糕,因为我的屏幕上的按钮确实很小。因此,解决方案是要么使按钮更大,要么使用 SVG 而不是 DOM 元素的光栅化版本。如何将SVG字符串渲染到画布?你可能知道,你可以将 SVG 放大和缩小到你想要的任何尺寸,而不会降低质量。如果将 DOM 元素导出为 SVG,你可以将其调整为你想要的大小,例如,以下代码会将选定的 DOM 元素呈现为 SVG 并将其显示到新的浏览器选项卡中:
let domNode = document.getElementById("myDiv");
// 1. Render the selected node to SVG
domtoimage.toSvg(domNode).then(function(SVG){
// 2. Load the SVG string (it looks something like this:
// data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="1623" height="64"><foreignObject x="0" y="0" width="100%" height="100%"><div id="myDiv" ....
let image = new Image();
image.src = SVG;
// 3. Launch a new tab in the browser and load the image to see the preview
let newWindow = window.open("");
newWindow.document.write(image.outerHTML);
});
然后,在新选项卡中,你将看到图像看起来非常清晰,你可以将图像调整到你想要的大小而不会降低质量(我们将其调整为3500 像素的图片,与原始大小相比,这是非常大的)纽扣):
SVG字符串如何渲染到画布?你可以稍后将其光栅化为流行的格式,如 PNG 或 JPEG,但质量不错!在本教程中,我将向你展示如何轻松使用 JavaScript 将 SVG 字符串或 SVG 文件渲染为图像,并将其调整为你想要保持其原始质量的大小。
1. 创建/获取 SVG 数据 URL
SVG字符串渲染到画布实例:数据 URL(以data:
方案为前缀的 URL)允许内容创建者在文档中嵌入小文件。在我们的例子中,我们的 SVG 文件数据方案将是:
重要提示:如果你对纯 SVG 数据进行 URL 编码以编码不应出现在 URL 中的字符会更好。
data:image/svg+xml;charset=utf-8,[The URL Encoded Plain Data of SVG should be here]
请注意,与使用 Base64 编码的其他格式不同,我们将需要数据 URL 中的纯数据。对于此示例,我们将使用来自 Wikipedia的广为人知的SVG Tiger。SVG 字符串可以来自任何地方,可以从 Web 资源下载,在浏览器中创建或作为 dom-to-image 库的输出,这一步的重点是你知道它需要在数据 URL 格式。
2.测试是否可以在Image中渲染SVG
SVG字符串如何渲染到画布?要测试你创建的 SVG 数据 URL 是否有效,你可以轻松地将其用作 HTML 中图像元素的来源。在这个例子中,我们将使用 Wikipedia 中提到的 SVG Tiger,我们将手动创建它,将 SVG 存储到一个字符串变量中,然后将数据 URL 方案添加到 URL 编码的 SVG 中:
<!-- An image element where the DataURL will be displayed -->
<img src="" id="test" />
<script>
// 1. Prepare SVG String
let SVGString = `
<svg id="svg2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 900" version="1.1">
<g id="g4" fill="none" transform="matrix(1.7656463,0,0,1.7656463,324.90716,255.00942)">
<g id="g6" stroke-width="0.17200001" stroke="#000" fill="#FFF">
<path id="path8" d="m-122.3,84.285s0.1,1.894-0.73,1.875c-0.82-0.019-17.27-48.094-37.8-45.851,0,0,17.78-7.353,38.53,43.976z"/>
</g>
....
.... (rest of the SVG String, note that we remove the following string from the SVG: <?xml version="1.0" encoding="UTF-8" standalone="no"?>)
....
</svg>
`;
// 2. Convert to Data URL
let dataURL = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(SVGString);
// 3. Set the DataURL as source of the test image
document.getElementById("test").src = dataURL;
</script>
你可以在以下小提琴中看到这一点,它应该在 Image 元素中显示 SVG 老虎:
现在知道 SVG 数据 URL 是有效的(只要你期望从给定 SVG 获得的图像出现在 img 元素中),你就可以继续下一步。
3. 在 Canvas 中渲染 SVG 并将其导出为任意大小的图像
如何将SVG字符串渲染到画布?现在是时候实现你正在寻找的内容,将 SVG 渲染到画布中以将其调整为你想要的任何大小。实现的逻辑如下。你需要一个空画布,你应该在其中渲染具有自定义大小的 SVG,然后你可以将其导出为 PNG 或 JPEG:
<canvas id="myOutputCanvas"></canvas>
<script>
// 1. Obtain the canvas element and access its context
let canvas = document.getElementById('myOutputCanvas');
let ctx = canvas.getContext("2d");
// 2. Declare the new width of the image that you want to generate in pixels
// e.g create an image of 1000 pixels of width from the given SVG
// note: the height is automatically calculated to preserve aspect ratio
let newWidth = 1000;
// 3. Create an image element to load the SVG
let img = new Image();
// 4. Once the SVGDataURL is rendered in the Image element
// proceed to render it in the empty canvas that will contain
// the same image, but in the size that you want preserving the
// sharpness of the SVG string
img.onload = function() {
// Declare initial dimensions of the image
let originalWidth = img.width;
let originalHeight = img.height;
// Declare the new width of the image
// And calculate the new height to preserve the aspect ratio
img.width = newWidth;
img.height = (originalHeight / originalWidth) * newWidth;
// Set the dimensions of the canvas to the new dimensions of the image
canvas.width = img.width;
canvas.height = img.height;
// Render image in Canvas
ctx.drawImage(img, 0, 0, img.width, img.height);
// That's it! If your canvas is visible, you may now see
// the image of the new size!
// Export the canvas to blob
// You may export this now as a base64 data URL or blob
// canvas.toBlob(function(blob){
// do something with the blob
//}, "image/png", 1);
};
// Load the DataURL of the SVG
img.src = "data:image/svg+xml;charset=utf-8,[The URL Encoded Plain Data of SVG should be here, replace this with the data from step #1]";
</script>
你可以在以下小提琴中看到此实现的实时示例,你可以在其中简单地将 SVG 字符串提供到 textarea 中,设置输出图像的新宽度,然后将其导出为你想要的图像格式:
快乐编码❤️!