Convert inline SVG to Base64 string

2020-01-30 05:17发布

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?

5条回答
\"骚年 ilove
2楼-- · 2020-01-30 05:35

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/

查看更多
来,给爷笑一个
3楼-- · 2020-01-30 05:36

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);  
}
查看更多
Root(大扎)
4楼-- · 2020-01-30 05:36

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 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);
查看更多
Animai°情兽
5楼-- · 2020-01-30 05:38

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!

查看更多
何必那么认真
6楼-- · 2020-01-30 05:55

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 i.e. data:image/svg+xml;base64, and there you have it.

查看更多
登录 后发表回答