How can I get png(base64) with images inside of svg in Google Charts?

倾然丶 夕夏残阳落幕 提交于 2020-01-08 18:01:47

问题


How can I get base64 with image inside of svg? Check this Fiddle that I got from another question. If you see the second graphic, its not generating the image that overlays the bar.

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())

回答1:


In order to save this svg to a png, which keeps the linked <image> then you'll have to encode each <image>'s href to a dataURL first.

Edit

I rewrote the original snippets (which can still be found in the edit history).

  • I changed the <image> tags to <use>. This results in a much smaller memory usage.

  • I also added a fallback for IE11, which accepts to encode the external image to data URL, but still fails to convert svg to png via canvas. The fallback will replace the destination <img>tag, with the canvas. The later can be saved by user with a right click.

  • A few caveats :
    It doesn't work in Safari 7, and maybe in other outdated webkit browsers. That's a strange bug, since it does work like a charm in localhost, but won't on any other network (even on my home network, using 192.168.xxx).
    IE 9 & IE 10 will fail to convert the external images to data URL, CORS problem.

// 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 = 'https://dl.dropboxusercontent.com/s/13dv8vzmrlcmla2/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 <use>
  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;    }
<script src="http://www.google.com/jsapi?.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="visualization"></div>
Right-click this image to save it:
<br>
<img id="chartImg" />



回答2:


This example creates an svg container populated by an image. In my example the image is an svg image but you should be able to put in any type of image (jpg, png, gif). The container is created first then the image is created inside the container.

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



回答3:


Note, When converted to src of img element retained blue background-color .

Try , after .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/



来源:https://stackoverflow.com/questions/29975138/how-can-i-get-pngbase64-with-images-inside-of-svg-in-google-charts

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!