html2canvas icon indicating copy to clipboard operation
html2canvas copied to clipboard

SVG Element not rendered in html2Canvas

Open julienlaurent-migso opened this issue 2 years ago • 5 comments

Please make sure you are testing with the latest release of html2canvas. Old versions are not supported and issues reported for them will be closed.

Please follow the general troubleshooting steps first:

  • [ x] You are using the latest version
  • [ x] You are testing using the non-minified version of html2canvas and checked any potential issues reported in the console

Bug reports:

I have a roadmap with svg elements to represent links between two items like this : image

the svg code looks like : image

each time that i try to print to png, my links are not rendered: image

My generation code is :

  html2canvas(
    document.getElementById("roadmapPrint"),
    {
      backgroundColor:null,
    }
    ).then(function(canvas) {
        var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"); 
        var a = document.createElement('a');
        a.href = image ;
        a.id = "tempAtoDelete"
        a.download = "filename.png";
        document.body.appendChild(a);
         a.click();
        let aToDelete = document.getElementById("tempAtoDelete");
        document.body.removeChild(aToDelete);
})

Do you have some advices ? i read that your library is able to manage svg elements, is it the case ? Thank you a lot for your help,

Specifications:

  • html2canvas version tested with: "^1.4.0"
  • Browser & version: Google Chrome Version 96.0.4664.110 (Build officiel) (64 bits)
  • Operating system: Windows

julienlaurent-migso avatar Jan 06 '22 13:01 julienlaurent-migso

Facing same issue , any solution kindly suggest

sandhya225 avatar Feb 24 '22 01:02 sandhya225

hi @sandhya225, I have fixed my issue converting all svg elements to canvas before use html2canvas librairy. This was an old solution (6 years old) but it works fine. @niklasvh : there is another way to do that ?

See my steps below:

  1. install the version 1.5.3 of canvg librairy and import the canvg function (for information this version is dowloaded more than 140000 per week..) (there is no dependence vulnerability with the last version of node/npm/CRA)

npm install [email protected]

import canvg from 'canvg'

  1. get all your svg element and create a canvas for each (track them to an array to delete them after)
//FOR EACH SVG ELEMENT, A CANVAS WILL BE CREATED => AT THE END WE NEED TO DELETE THEM
  var svgNodesToRemove = [];

  //GET ALL SVG ELEMENT
  let svgElements = document.body.querySelectorAll('svg');

  //LOOP ON EACH ELEMENT
  svgElements.forEach(function(item) {

    //YOU CAN PROCEED TO ELEMENT TREATMENT BEFORE CONVERT TO CANVAS 
    let children = item.childNodes
    children.forEach(function(child) {

      //IN MY CASE I USE ANIMATION FOR MY SVG PATH AND NEED TO FIX THE OPACITY STYLE
      child.style.opacity = 1;
    })

    //TRIM EACH ITEM IN THE LOOP
    let svg = item.outerHTML.trim();

    //CREATE CANVAS FOR YOUR CURRENT SVG
    var canvas = document.createElement('canvas');

    //UPDATE THE NEEDED ATTRIBUTE WITH AND HEIGHT
    canvas.width = item.getBoundingClientRect().width;
    canvas.height = item.getBoundingClientRect().height;

    //CONVERT SVG TO CANVAS
    canvg(canvas, svg); 

    //UPDATE THE CANVAS POSITION TO THE SVG ELEMENT
    if (item.style.position) {
        canvas.style.position += item.style.position;
        canvas.style.left += item.style.left;
        canvas.style.top += item.style.top;
    }

    //APPEND THE CANVAS TO THE DOM
    item.parentNode.appendChild(canvas);

    //TRACK CANVAS TO BE DELTED AFTER 
    svgNodesToRemove.push(canvas)

  });

I did not hidde my current svg element in the dom because there are not rendered...

  1. now you are able to use html2canvas :
html2canvas(
    document.getElementById("roadmapPrint"),
    {
      backgroundColor:null,
    }
  ).then(function(canvas){
  
      //YOUR LOGIC
      //....

      //DELETE SVG CANVAS
      svgNodesToRemove.forEach(function(element){
        element.remove();
      })

}).catch((err)=>{

    //DISPLAY ERROR
    console.log(err)

    //DELETE SVG CANVAS
    svgNodesToRemove.forEach(function(element){
      element.remove();
    })
  });

hope it helps

julienlaurent-migso avatar Feb 24 '22 07:02 julienlaurent-migso

@julienlaurent-migso very good

SpringHgui avatar Aug 04 '22 05:08 SpringHgui

If I use <use> tag, the solution others mentioned is not worked like: <svg aria-hidden='true' className='example'> <use xlinkHref={item.icon} /> </svg> So, I can not get TRUE outerHTML in svg

Curacao-lb avatar Feb 06 '23 09:02 Curacao-lb

If I use <use> tag, the solution others mentioned is not worked like: <svg aria-hidden='true' className='example'> <use xlinkHref={item.icon} /> </svg> So, I can not get TRUE outerHTML in svg

Your problem solved?

trry-hub avatar Jan 22 '24 10:01 trry-hub