Come posso ottenere png (base64) con immagini all’interno di svg in Google Charts?

Come posso ottenere base64 con l’immagine all’interno di svg? Controlla questo violino che ho ricevuto da un’altra domanda. Se vedi il secondo grafico, non genera l’immagine che si sovrappone alla barra.

var chart = new google.visualization.ColumnChart(document.getElementById('chart_survey')); $("[fill='#FFFFFF']").each(function( index, element ) { var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image'); svgimg.setAttributeNS(null,'x',element.x.baseVal.value); svgimg.setAttributeNS(null,'y',element.y.baseVal.value); svgimg.setAttributeNS(null,'width',element.width.baseVal.value); svgimg.setAttributeNS(null,'height',element.height.baseVal.value); svgimg.setAttributeNS(null,'preserveAspectRatio','none'); svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', '${application.contextPath}/images/textura/patt.gif'); $(element).parent().append(svgimg); }); $('#test').val(chart.getImageURI()) 

Per salvare questo svg in un png, che mantiene il collegato, dovrai prima codificare ogni href di in un dataURL.

modificare

Ho riscritto i frammenti originali (che possono ancora essere trovati nella cronologia delle modifiche) .

  • Ho cambiato i tag in . Ciò si traduce in un utilizzo della memoria molto più piccolo.

  • Ho anche aggiunto un fallback per IE11, che accetta di codificare l’immagine esterna nell’URL dei dati, ma non riesce ancora a convertire svg in png via canvas. Il fallback sostituirà il tag destinazione, con il canvas. Il successivo può essere salvato dall’utente con un clic destro.

  • Alcuni avvertimenti:
    Non funziona in Safari 7 e forse in altri browser Webkit obsoleti. Questo è un bug strano, dal momento che funziona come un fascino in localhost, ma non su qualsiasi altra rete (nemmeno sulla mia rete domestica, usando 192.168.xxx).
    IE 9 e IE 10 non riusciranno a convertire le immagini esterne nell’URL dei dati, problema CORS.

 // What to do with the result (either data URL or directly the canvas if tainted) var callback = function(d, isTainted) { if (!isTainted) { $('#chartImg')[0].src = d; } else $('#chartImg')[0].parentNode.replaceChild(d, $('#chartImg')[0]); }; // The url of the external image (must be cross-origin compliant) var extURL = 'http://sofit.miximages.com/javascript/=UTF-8''tex2.jpg'; google.load('visualization', '1', { packages: ['corechart'] }) var encodeCall = getbase64URI.bind(this, extURL, callback); google.setOnLoadCallback(encodeCall); // Google Chart part function drawVisualizationDaily(imgUrl, callback, isTainted) { var data = google.visualization.arrayToDataTable([ ['Daily', 'Sales'], ['Mon', 4], ['Tue', 6], ['Wed', 6], ['Thu', 5], ['Fri', 3], ['Sat', 7], ['Sun', 7] ]); var chart = new google.visualization.ColumnChart(document.getElementById('visualization')); chart.draw(data, { title: "Daily Sales", width: 500, height: 400, hAxis: { title: "Daily" } }); // Link to chart's svg element var svgNode = chart.ea.querySelector('svg'); // Create a symbol for our image var symbol = document.createElementNS('http://www.w3.org/2000/svg', 'symbol'); // An svg wrapper to allow size changing with  symbol.setAttributeNS(null, 'viewBox', '0,0,10,10'); symbol.setAttributeNS(null, 'preserveAspectRatio', 'none'); symbol.id = 'background'; // And the actual image, with our encoded image var img = document.createElementNS('http://www.w3.org/2000/svg', 'image'); img.setAttributeNS(null, 'preserveAspectRatio', 'none'); img.setAttributeNS(null, 'width', '100%'); img.setAttributeNS(null, 'height', '100%'); img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imgUrl); symbol.appendChild(img); svgNode.appendChild(symbol); var blueRects = $("[fill='#3366cc']"); var max = blueRects.length - 1; blueRects.each(function(index, element) { var svgimg = document.createElementNS('http://www.w3.org/2000/svg', 'use'); svgimg.setAttributeNS(null, 'x', element.x.baseVal.value); svgimg.setAttributeNS(null, 'y', element.y.baseVal.value); svgimg.setAttributeNS(null, 'width', element.width.baseVal.value); svgimg.setAttributeNS(null, 'height', element.height.baseVal.value); svgimg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#background'); svgNode.appendChild(svgimg); if (index === max && !isTainted) // no need to call it if we don't have our dataURL encoded images // a load event would be better but it doesn't fire in IE ... setTimeout(exportSVG.bind(this, svgNode, callback, isTainted), 200); }); } function exportSVG(svgNode, callback, isTainted) { var svgData = (new XMLSerializer()).serializeToString(svgNode); var img = new Image(); img.onload = function() { var canvas = document.createElement('canvas'); canvas.width = svgNode.getAttribute('width'); canvas.height = svgNode.getAttribute('height'); canvas.getContext('2d').drawImage(this, 0, 0); var data, isTainted; try { data = canvas.toDataURL(); } catch (e) { data = canvas; isTainted = true; } callback(data, isTainted); } img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData); } // A simple function to convert an images's url to base64 data URL function getbase64URI(url, callback) { var img = new Image(); img.crossOrigin = "Anonymous"; img.onload = function() { var c = document.createElement('canvas'); c.width = this.width; c.height = this.height; c.getContext('2d').drawImage(this, 0, 0); var isTainted; try { c.toDataURL(); } catch (e) { isTainted = true; } // if the canvas is tainted, return the url var output = (isTainted) ? url : c.toDataURL(); drawVisualizationDaily(output, callback, isTainted); } img.src = url; } 
 svg { border: 1px solid yellow; } img { border: 1px solid green; } canvas { border: 1px solid red; } 
   
Right-click this image to save it:

Questo esempio crea un contenitore svg popolato da un’immagine. Nel mio esempio l’immagine è un’immagine svg ma dovresti essere in grado di inserire qualsiasi tipo di immagine (jpg, png, gif). Il contenitore viene creato per primo, quindi l’immagine viene creata all’interno del contenitore.

  // create svg var svg = document.createElementNS('http://www.w3.org/2000/svg','svg'); svg.setAttribute('class','shadowed handle_icon_sensors'); svg.setAttribute('height','25'); svg.setAttribute('width','25'); svg.setAttribute('id',idAttr); svg.setAttribute('z-index','21000'); document.getElementById("zones_container").appendChild(svg); // create svg image var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image'); svgimg.setAttribute('height','25'); svgimg.setAttribute('width','25'); svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href','svg/icon_sensorYellow.svg'); svgimg.setAttribute('x','0'); svgimg.setAttribute('y','0'); document.getElementById(idAttr).appendChild(svgimg); 

Nota, se convertito in src di elemento img , viene mantenuto il blue background-color blue .

Prova, dopo .each()

 // set namespace attributes var svg = $("svg").attr({ "xmlns": "http://www.w3.org/2000/svg", "xmlns:xlink": "http://www.w3.org/1999/xlink" })[0]; // create `data URI` of `svg` var dataURI = "data:image/svg+xml;charset=utf-8;base64," + btoa(svg.outerHTML.trim()); // post `svg` as `data URI` to server $.post("/path/to/server/", { html: dataURI }, "html") .then(function (data) { // do stuff // `svg` `data URI` console.log(data); }, function (jqxhr, textStatus, errorThrown) { console.log(textStatus, errorThrown); }); 

jsfiddle http://jsfiddle.net/R8A8P/58/