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

后端 未结 3 704
攒了一身酷
攒了一身酷 2020-11-28 16:52

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

相关标签:
3条回答
  • 2020-11-28 17:12

    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/

    0 讨论(0)
  • 2020-11-28 17:18

    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);
    
    0 讨论(0)
  • 2020-11-28 17:25

    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" />

    0 讨论(0)
提交回复
热议问题