My posts are usually notes and reference materials for myself, which I publish here with the hope that others might find them useful.
TL;DR:
let svg = `<svg xmlns="http://www.w3.org/2000/svg" ...`;
let blob = new Blob([svg], {type: 'image/svg+xml'});
let url = URL.createObjectURL(blob);
let image = document.createElement('img');
image.src = url;
image.addEventListener('load', () => URL.revokeObjectURL(url), {once: true});
It is sometimes useful to compose an SVG programmatically as a string. Using that string as the src
of an image is fairly straightforward (with one "gotcha".)
Step one: you need a string of SVG text.
let svg = `<svg ...`;
Step two: convert the string to a blob.
let blob = new Blob([svg], {type: 'image/svg+xml'});
Step three: create a URL to the blob.
let url = URL.createObjectURL(blob);
Step four: create an image referencing the URL.
let image = document.createElement('img');
image.src = url;
Step five: revoke the URL once the image loads for cleanup.
image.addEventListener('load', () => URL.revokeObjectURL(url), {once: true});
However, the following does not work:
let svg = `
<svg width="50" height="50">
<circle cx="25" cy="25" r="20"/>
</svg>`;
This results in a broken image:
The xmlns
attribute must be included on the <svg>
element:
let svg = `
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg">
<circle cx="25" cy="25" r="20"/>
</svg>`;
And now it works:
Chrome is not tolerant of a missing xmlns
attribute in this case, which is, I guess, consistent: only inline <svg>
s, embedded inside HTML markup, are allowed to omit the xmlns
attribute. External SVGs, used as the src
of an <img>
, must include it, apparently even if the SVG is "inline" in the sense that it created by the document itself as a blob, and even if the MIME type is image/svg+xml
.
Top comments (4)
Second option would be
data:image/svg+xml,
andencodeURIComponent
. See codepen.io/tigt/post/optimizing-sv...Blob is not defined in Node.js file?? Any Suggestions?
This is code designed to run in the browser, not in Node.
This saved me some hours of search for a solution, Thanks :)