简体   繁体   中英

Convert inline SVG to Base64 string

I want to send an inline SVG image to a PHP script to Convert it to PNG with Imagick. For that I have to know how to get a base64 String out on an inline SVG. For canvas objects its a simple ".toDataURL()" but that doesn't work with inline SVGs, because its not a global function of elements.

test = function(){
    var b64 = document.getElementById("svg").toDataURL();
    alert(b64);
}

http://jsfiddle.net/nikolang/ccx195qj/1/

But how to do it for inline SVGs?

Use XMLSerializer to convert the DOM to a string

var s = new XMLSerializer().serializeToString(document.getElementById("svg"))

and then btoa can convert that to base64

var encodedData = window.btoa(s);

Just prepend the data URL intro ie data:image/svg+xml;base64, and there you have it.

You can do it relatively straightforwardly as follows. The short version is

  1. Make an image not attached to the dom
  2. Set its size to match the source svg
  3. base64 encode the source svg , append the relevant data, set img src
  4. Get the canvas context; .drawImage the image

    <script type="text/javascript"> window.onload = function() { paintSvgToCanvas(document.getElementById('source'), document.getElementById('tgt')); } function paintSvgToCanvas(uSvg, uCanvas) { var pbx = document.createElement('img'); pbx.style.width = uSvg.style.width; pbx.style.height = uSvg.style.height; pbx.src = 'data:image/svg+xml;base64,' + window.btoa(uSvg.outerHTML); uCanvas.getContext('2d').drawImage(pbx, 0, 0); } </script>

     <svg xmlns="http://www.w3.org/2000/svg" width="467" height="462" id="source"> <rect x="80" y="60" width="250" height="250" rx="20" style="fill:#ff0000; stroke:#000000;stroke-width:2px;" /> <rect x="140" y="120" width="250" height="250" rx="40" style="fill:#0000ff; stroke:#000000; stroke-width:2px; fill-opacity:0.7;" /> </svg> <canvas height="462px" width="467px" id="tgt"></canvas>

JSFiddle: https://jsfiddle.net/oz3tjnk7/

I just try to collect and explain all great ideas on this issue. This works on both Chrome 76 and Firefox 68

var svgElement = document.getElementById('svgId');

// Create your own image
var img = document.createElement('img');

// Serialize the svg to string
var svgString = new XMLSerializer().serializeToString(svgElement);

// Remove any characters outside the Latin1 range
var decoded = unescape(encodeURIComponent(svgString));

// Now we can use btoa to convert the svg to base64
var base64 = btoa(decoded);

var imgSource = `data:image/svg+xml;base64,${base64}`;

img.setAttribute('src', imgSource);

I had the same problem while working on SVG based Floorplan Editor, after drawing a floorplan we have to save it for later use. Long story, code is better than talking, Here is the final code which worked for me:

async saveFloorplan() {
  const svgElem = document.querySelector('#svg-element');
  let xmlSource = new XMLSerializer().serializeToString(svgElem);

  if (!xmlSource.match(/^<svg[^>]+xmlns="http:\/\/www\.w3\.org\/2000\/svg"/)) {
    xmlSource = xmlSource.replace(/^<svg/, '<svg xmlns="http://www.w3.org/2000/svg"');
  }
  if (!xmlSource.match(/^<svg[^>]+"http:\/\/www\.w3\.org\/1999\/xlink"/)) {
    xmlSource = xmlSource.replace(/^<svg/, '<svg xmlns:xlink="http://www.w3.org/1999/xlink"');
  }
  // add xml declaration
  xmlSource = `<?xml version="1.0" standalone="no"?>\r\n${xmlSource}`;

  const svg64 = encodeURIComponent(xmlSource);
  const b64Start = 'data:image/svg+xml;charset=utf-8,';

  const imgEl = new Image();
  const image64 = b64Start + svg64;
  imgEl.src = image64;

  const blobResp = await fetch(imgEl.src);
  const blob = await blobResp.blob();

  const payload = {...}

  payload.fileExtension = 'svg';
  payload.fileSize = blob.size;

  const formData = new FormData();
  formData.append('file', blob);

  const uploaded = await api.uploadFile(formData);  
}

This line will perform the conversion:

window.btoa($("svg").wrap("<div id='xyz'/>").parent().html());

Make sure that the proper charset/encoding has been selected!

// 1. get the element
let e = document.getElementById("svg");

// 2. get the string representation of the element
var s = new XMLSerializer().serializeToString(e);
// or 
var s = e.outerHTML;

// 3. convert the string to url
// convert to utf8
var url = "data:image/svg+xml;utf8," + encodeURIComponent(s);
// convert to base64
var url = "data:image/svg+xml;base64," + window.btoa(unescape(encodeURIComponent(s)));
// or
var url = "data:image/svg+xml;base64," + Buffer.from(s, "utf-8").toString("base64")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM