Je veux envoyer une image SVG en ligne vers un script PHP pour la convertir en PNG avec Imagick. Pour cela, je dois savoir comment obtenir une chaîne base64 sur un SVG en ligne. Pour les objets de canevas c'est un simple ".toDataURL ()" mais cela ne fonctionne pas avec les SVG en ligne, car ce n'est pas une fonction globale des éléments.
test = function(){
var b64 = document.getElementById("svg").toDataURL();
alert(b64);
}
http://jsfiddle.net/nikolang/ccx195qj/1/
Mais comment faire pour les SVG en ligne?
Utilisez XMLSerializer pour convertir le DOM en chaîne
var s = new XMLSerializer().serializeToString(document.getElementById("svg"))
puis btoa peut convertir cela en base64
var encodedData = window.btoa(s);
Ajoutez simplement l'intro de l'URL de données, c'est-à-dire data:image/svg+xml;base64,
Et voila.
Vous pouvez le faire de manière relativement simple comme suit. La version courte est
svg
base64
encoder la source svg
, ajouter les données pertinentes, définir img src
Obtenez le contexte canvas
; .drawImage
l'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>
J'ai eu le même problème en travaillant sur l'éditeur de plan d'étage basé sur SVG, après avoir dessiné un plan d'étage, nous devons le sauvegarder pour une utilisation ultérieure. Longue histoire, le code vaut mieux que de parler, voici le code final qui a fonctionné pour moi:
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);
}
Cette ligne effectuera la conversion:
window.btoa($("svg").wrap("<div id='xyz'/>").parent().html());
Assurez-vous que le bon jeu de caractères/encodage a été sélectionné!
J'essaie simplement de rassembler et d'expliquer toutes les bonnes idées sur cette question. Cela fonctionne sur les deux Chrome 76 et 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);