vue.jssvgcanvascanvg

Downloading Canvas as JPG/PNG returns blank image


So, I'm using canvg and the function which converts svg file to a jpg/png just downloads and ignores id of a svg block element, so I get the blank image, what could be wrong? Maybe Vue does not support converting SVG to jpg/png using canvas. Here is the javascript:

import canvg from "canvg";

 function SVG2PNG(svg, callback) {
  var canvas = document.createElement("canvas");
  var w = 800;
  var h = 400;
  canvas.width = w;
  canvas.height = h; // Create a Canvas element.
  var ctx =  canvas.getContext("2d"); // For Canvas returns 2D graphic.
  debugger;
  var data = svg.outerHTML; // Get SVG element as HTML code.
  canvg.from(canvas, data); // Render SVG on Canvas.
  callback(canvas); // Execute callback function.
}

function generateLink(fileName, data) {
  var link = document.createElement("a");
  link.download = fileName;
  link.href = data;
  return link;
}

export default {
  methods: {
    tipka() {
        debugger;
      var element = document.getElementById("svg"); // Get SVG element.
      SVG2PNG(element, function (canvas) {
        // Arguments: SVG element, callback function.
        var base64 = canvas.toDataURL("image/png"); // toDataURL return DataURI as Base64 format.
        generateLink("SVG2PNG-01.png", base64).click(); // Trigger the Link is made by Link Generator and download.
      });
    },
  },
};

Here is the ending of svg tag: enter image description here This is the start of svg tag: enter image description here


Solution

  • Per the documentation for Canvg.from, you need to pass it your drawing context, not the canvas itself. So change this line:

    canvg.from(canvas, data); // Render SVG on Canvas.
    

    to:

    canvg.from(ctx, data); // Render SVG on Canvas.
    

    It also appears, per this answer, that you will need to replace your viewBox attribute on the <svg> with width and height attributes, like:

    <svg class="shape" version="1.1" id="svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
    width="400" height="400" style="enable-background:new 0 0 400 400;" xml:space="preserve">
    

    You can then actually bypass canvg entirely with the function rewritten like this:

    function SVG2PNG(svg, callback) {
        var canvas = document.createElement("canvas");
        canvas.width = 400;
        canvas.height = 400; // Create a Canvas element.
        var ctx = canvas.getContext("2d"); // For Canvas returns 2D graphic.
        var svgString = svg.outerHTML;
        var img = new Image();
        img.addEventListener('load', () => {
            ctx.drawImage(img, 0, 0, 400, 400);
            callback(canvas.toDataURL("image/png")); // toDataURL return DataURI as Base64 format.
        });
        img.src = 'data:image/svg+xml,' + svgString;
    }
    

    (Note that it now returns the data URL, not the canvas.)