This is an old question, in 2022 we have ES6 and we don't need 3rd party libraries.
Here is a very basic way to convert svg
images into other formats.
The trick is to load the svg
element as an img
element, then use a canvas element to convert the image into the desired format. So, four steps are needed:
- Extract
svg
asxml
data string. - Load the
xml
data string into aimg
element - Convert the
img
element to adataURL
using acanvas
element - Load the converted
dataURL
into a newimg
element
Step 1
Extracting a svg
as xml
data string is simple, we don't need to convert it as a base64 string. We just serialize it as XML then we encode the string as a URI:
// Data header for a svg image: const dataHeader = 'data:image/svg+xml;charset=utf-8'// Serialize it as xml string:const serializeAsXML = $e => (new XMLSerializer()).serializeToString($e)// Encode URI data as UTF8 data:const encodeAsUTF8 = s => `${dataHeader},${encodeURIComponent(s)}`// Select the element:const $svg = document.getElementById('svg-container').querySelector('svg')// Encode it as a data string:const svgData = encodeAsUTF8(serializeAsXML($svg))
Note:
If you need a base64 data you can use this option:
...// Encode URI data as base64 data:const encodeAsB64 = s => `${dataHeader};base64,${btoa(s)}`...// Encode it as a data string:const svgData = encodeAsB64(serializeAsXML($svg))
Step 2
Loading the xml
data string into a img
element:
// This function returns a Promise whenever the $img is loadedconst loadImage = async url => { const $img = document.createElement('img') $img.src = url return new Promise((resolve, reject) => { $img.onload = () => resolve($img) $img.onerror = reject $img.src = url })}
Step 3
Converting the img
element to a dataURL
using a canvas
element:
const $canvas = document.createElement('canvas')$canvas.width = $svg.clientWidth$canvas.height = $svg.clientHeight$canvas.getContext('2d').drawImage(img, 0, 0, $svg.clientWidth, $svg.clientHeight)return $canvas.toDataURL(`image/${format}`, 1.0)
Step 4
Loading the converted dataURL
into a new img
element:
const $img = document.createElement('img')$img.src = dataURL$holder.appendChild($img)
Here you have a working snippet:
const dataHeader = 'data:image/svg+xml;charset=utf-8'const $svg = document.getElementById('svg-container').querySelector('svg')const $holder = document.getElementById('img-container')const $label = document.getElementById('img-format')const destroyChildren = $element => { while ($element.firstChild) { const $lastChild = $element.lastChild ?? false if ($lastChild) $element.removeChild($lastChild) }}const loadImage = async url => { const $img = document.createElement('img') $img.src = url return new Promise((resolve, reject) => { $img.onload = () => resolve($img) $img.onerror = reject })}const serializeAsXML = $e => (new XMLSerializer()).serializeToString($e)const encodeAsUTF8 = s => `${dataHeader},${encodeURIComponent(s)}`const encodeAsB64 = s => `${dataHeader};base64,${btoa(s)}`const convertSVGtoImg = async e => { const $btn = e.target const format = $btn.dataset.format ?? 'png' $label.textContent = format destroyChildren($holder) const svgData = encodeAsUTF8(serializeAsXML($svg)) const img = await loadImage(svgData) const $canvas = document.createElement('canvas') $canvas.width = $svg.clientWidth $canvas.height = $svg.clientHeight $canvas.getContext('2d').drawImage(img, 0, 0, $svg.clientWidth, $svg.clientHeight) const dataURL = await $canvas.toDataURL(`image/${format}`, 1.0) console.log(dataURL) const $img = document.createElement('img') $img.src = dataURL $holder.appendChild($img)}const buttons = [...document.querySelectorAll('[data-format]')]for (const $btn of buttons) { $btn.onclick = convertSVGtoImg}
.wrapper { display: flex; flex-flow: row nowrap; width: 100vw;}.images { display: flex; flex-flow: row nowrap; width: 70%;}.image { width: 50%; display: flex; flex-flow: row wrap; justify-content: center;}.label { width: 100%; text-align: center;}
<div class="wrapper"><div class="item images"><div class="image left"><div class="label">svg</div><div id="svg-container"><svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="200" height="200" viewBox="0 0 248 204"><path fill="#1d9bf0" d="M221.95 51.29c.15 2.17.15 4.34.15 6.53 0 66.73-50.8 143.69-143.69 143.69v-.04c-27.44.04-54.31-7.82-77.41-22.64 3.99.48 8 .72 12.02.73 22.74.02 44.83-7.61 62.72-21.66-21.61-.41-40.56-14.5-47.18-35.07 7.57 1.46 15.37 1.16 22.8-.87-23.56-4.76-40.51-25.46-40.51-49.5v-.64c7.02 3.91 14.88 6.08 22.92 6.32C11.58 63.31 4.74 33.79 18.14 10.71c25.64 31.55 63.47 50.73 104.08 52.76-4.07-17.54 1.49-35.92 14.61-48.25 20.34-19.12 52.33-18.14 71.45 2.19 11.31-2.23 22.15-6.38 32.07-12.26-3.77 11.69-11.66 21.62-22.2 27.93 10.01-1.18 19.79-3.86 29-7.95-6.78 10.16-15.32 19.01-25.2 26.16z"/></svg></div></div><div class="image right"><div id="img-format" class="label"></div><div id="img-container"></div></div></div><div class="item buttons"><button id="btn-png" data-format="png">PNG</button><button id="btn-jpg" data-format="jpeg">JPG</button><button id="btn-webp" data-format="webp">WEBP</button></div></div>