html and Svg to Canvas javascript

24,374

Solution 1

You will need to use canvg library for drawing this svg to a temporary canvas and then remove that canvas once you take the screenshot using html2canvas.

Here is the link for canvg : https://github.com/canvg/canvg

Try this:

//find all svg elements in $container
//$container is the jQuery object of the div that you need to convert to image. This div may contain highcharts along with other child divs, etc
var svgElements= $container.find('svg');

//replace all svgs with a temp canvas
svgElements.each(function () {
    var canvas, xml;

    canvas = document.createElement("canvas");
    canvas.className = "screenShotTempCanvas";
    //convert SVG into a XML string
    xml = (new XMLSerializer()).serializeToString(this);

    // Removing the name space as IE throws an error
    xml = xml.replace(/xmlns=\"http:\/\/www\.w3\.org\/2000\/svg\"/, '');

    //draw the SVG onto a canvas
    canvg(canvas, xml);
    $(canvas).insertAfter(this);
    //hide the SVG element
    this.className = "tempHide";
    $(this).hide();
});

//...
//HERE GOES YOUR CODE FOR HTML2CANVAS SCREENSHOT
//...

//After your image is generated revert the temporary changes
$container.find('.screenShotTempCanvas').remove();
$container.find('.tempHide').show().removeClass('tempHide');

Solution 2

As the html2canvas don't take svg elements, you need to convert all svg elements to canvas before you call the html2canvas method. You could use the canvg library to convert all the svg to canvas. You can pass the jquery object(which needs to convert from svg to canvas, can also be a parent element) to the following method:

function svgToCanvas (targetElem) {
var nodesToRecover = [];
var nodesToRemove = [];

var svgElem = targetElem.find('svg');

svgElem.each(function(index, node) {
    var parentNode = node.parentNode;
    var svg = parentNode.innerHTML;

    var canvas = document.createElement('canvas');

    canvg(canvas, svg);

    nodesToRecover.push({
        parent: parentNode,
        child: node
    });
    parentNode.removeChild(node);

    nodesToRemove.push({
        parent: parentNode,
        child: canvas
    });

    parentNode.appendChild(canvas);
});

html2canvas(targetElem, {
    onrendered: function(canvas) {
        var ctx = canvas.getContext('2d');
        ctx.webkitImageSmoothingEnabled = false;
        ctx.mozImageSmoothingEnabled = false;
        ctx.imageSmoothingEnabled = false;
    }
    });
}

Solution 3

Your solution works beautifully. Since I am not using jQuery in my application, I had to change couple of lines in svgCanvas for getting the svg elements and iterating through them. The rest of the functions worked without any changes. My code is...

function svgToCanvas (targetElem) {
        var nodesToRecover = [];
        var nodesToRemove = [];

        var svgElems = document.getElementsByTagName("svg");

        for (var i=0; i<svgElems.length; i++) {
            var node = svgElems[i];
            var parentNode = node.parentNode;
            var svg = parentNode.innerHTML;

            var canvas = document.createElement('canvas');

            canvg(canvas, svg);

            nodesToRecover.push({
                parent: parentNode,
                child: node
            });
            parentNode.removeChild(node);

            nodesToRemove.push({
                parent: parentNode,
                child: canvas
            });

            parentNode.appendChild(canvas);
        }
}
Share:
24,374
user2622044
Author by

user2622044

Updated on August 08, 2020

Comments

  • user2622044
    user2622044 over 3 years
    <div id="Contents">
    <div style="float:left;margin-left:10px;">
    <svg></svg>
    </div>
    <div style="float:left;margin-left:10px;">
    <svg></svg>
    </div>
    </div>
    

    This is my html code. I want to convert it canvas image.

    html2canvas($("#Contents"), {
      onrendered: function(canvas) {
       window.open(canvas.toDataURL());
    
      }
    });
    

    I use html2canvas plugin for convert it to image but It does not show svg. I solve converting svg tp canvas but now html2canvas not working

      var $to=$("#MainContents").clone();
    
                $($to).children(".box").each(function() {
        var svg = ResizeArray[$(this).children(".box-content").children().attr("new-id")-1].svg();
                var Thiscanvas = document.createElement("canvas");
                Thiscanvas.setAttribute("style", "height:" + 100 + "px;width:" + 100+ "px;");
    
                canvg(Thiscanvas, svg);
    
                $(this).append(Thiscanvas);
    
            });
            html2canvas($($to), {
          onrendered: function(canvasq) {
            var w=window.open(canvasq.toDataURL());
            w.print();
          }
        });
    

    I can convert svg to canvas but html2canvas function not working.

  • user2622044
    user2622044 over 10 years
    Can I use html2canvas with canvg ? . I am gonna convert first canvg before use html2canvas. I think they are not work together.
  • Alessandro Minoccheri
    Alessandro Minoccheri over 10 years
    you can try it, see in the link that I have posted into my answer someone have tried already this
  • richdotjs
    richdotjs about 6 years
    Thank you so much for this! The snippet worked like a charm. I'm finally able to get it working. However, I still have to calibrate it as I'm noticing the snapshots cropping the charts in a weird way.
  • Mathijs Segers
    Mathijs Segers over 5 years
    Your code has quite some unused variables. I know it's old but you should probably look into it :-)
  • Agilanbu
    Agilanbu over 5 years
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. how to answer
  • 井上心叶
    井上心叶 over 4 years
    Thank you for your suggestion. I have revised the answer