Преобразование строки SVG в Base64

Я хочу отправить встроенный SVG-образ на PHP script, чтобы преобразовать его в PNG с помощью Imagick. Для этого я должен знать, как получить base64 String на встроенном SVG. Для объектов canvas это простой ".toDataURL()", но это не работает с встроенными SVG, потому что это не глобальная функция элементов.

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

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

Но как это сделать для встроенных SVG?

Ответ 1

Используйте XMLSerializer для преобразования DOM в строку

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

а затем btoa может преобразовать это в base64

var encodedData = window.btoa(s);

Просто добавьте URL-адрес URL-адреса данных, т.е. data:image/svg+xml;base64,, и там у вас есть.

Ответ 2

Вы можете сделать это относительно просто следующим образом. Короткая версия

  1. Сделать изображение, не привязанное к домену
  2. Установите его размер в соответствии с источником svg
  3. base64 кодировать источник svg, добавить соответствующие данные, установить img src
  4. Получите контекст canvas; .drawImage изображение

    <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

У меня была такая же проблема при работе с SVG Editor, после составления плана этажа, мы должны сохранить его для дальнейшего использования. Длинная история, код лучше, чем говорить, вот последний код, который работал для меня:

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);  
}

Ответ 4

Эта строка выполнит преобразование:

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

Убедитесь, что выбрана правильная кодировка/кодировка!

Ответ 5

Я просто пытаюсь собрать и объяснить все отличные идеи по этому вопросу. Это работает как на Chrome 76, так и на 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);