1

i am converting angular nvd3 chart to svg using html2canvas and canvg plugings but when i convert pie chart to png then i looks same as chart but when i convert line chart or area chart then its background goes to black and some circle drown on image. My code is

var svgElements = $("#container").find('svg');

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

                // canvg doesn't cope very well with em font sizes so find the calculated size in pixels and replace it in the element.
                $.each($(this).find('[style*=em]'), function (index, el) {
                    $(this).css('font-size', getStyle(el, 'font-size'));
                });

                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).attr('class', 'tempHide');
                $(this).hide();
            });


            html2canvas($("#container"), {
                onrendered: function (canvas) {
                    var a = document.createElement("a");
                    a.download = "Dashboard.png";
                    a.href = canvas.toDataURL("image/png");
                    a.click();
                    var imgData = canvas.toDataURL('image/png');

                    var doc = new jsPDF('p', 'mm','a4');
                    var width = doc.internal.pageSize.width;    
                    var height = doc.internal.pageSize.height;

                    doc.addImage(imgData, 'PNG',  0, 0, width, height);
                    doc.save('Dashboard.pdf');
                }
            });

            $("#container").find('.screenShotTempCanvas').remove();
            $("#container").find('.tempHide').show().removeClass('tempHide');

this is area chart image with some unknown circle on chart

Help me guys. Thanks In Advance

Dixit
  • 1,359
  • 3
  • 18
  • 39

2 Answers2

3

Your svg elements are being styled by the external stylesheet nv.d3.min.css .

canvg seems unable to access external style sheets, so you need to append it directly in your svg node.

To do so, if your style sheet is hosted on the same domain as your scripts, you can do something like :

var sheets = document.styleSheets;
var styleStr = '';
Array.prototype.forEach.call(sheets, function(sheet){
    try{ // we need a try-catch block for external stylesheets that could be there...
        styleStr += Array.prototype.reduce.call(sheet.cssRules, function(a, b){
            return a + b.cssText; // just concatenate all our cssRules' text
            }, "");
        }
    catch(e){console.log(e);}
});
// create our svg nodes that will hold all these rules
var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
var style = document.createElementNS('http://www.w3.org/2000/svg', 'style');
style.innerHTML = styleStr;
defs.appendChild(style);
// now append it in your svg node
thesvg[0].insertBefore(defs, thesvg[0].firstElementChild);

So now you can call the XMLSerializer, and canvg will be happy.
(note that this is not only a canvg limitation, the same applies for every way to draw an svg on a canvas).

Forked plunkr, where I copied the nv.d3.min.css's content to a same-origin style.css.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • 1
    @dkc007, han, this is a chrome bug and an angular bad implementation.. ng uses some hackish `[ng\:something]` selector, while they should use `[ng|something]`... Chrome accepts happily this hack for rendering, but it stores only `[ng:something]` in the stylesheet rules, while this later is invalid and throws this error... here is an other fork which *quick-fixes* it, by avoiding the stylesheet which has these rules : http://plnkr.co/edit/ZgT2P4Tu0Z9x63QwPNFB?p=preview – Kaiido Dec 27 '16 at 13:39
  • please check this plunker i am unable to see any image in downloaded image http://plnkr.co/edit/UaI7rtfMLxxCKt5xy6s3?p=preview – Dixit Dec 27 '16 at 14:13
  • @dkc007 I told you I am at work, which means that I've got a job that gives me money that I need and weirdly enough, my boss (the one that gives me money) prefer to see me working for him in working hours rather than for some unknown person on the internet. You'll have to wait. – Kaiido Dec 28 '16 at 10:29
1

Very late to the conversation but I just wanted to add that the solution as described by Kaiido, put very simply, is to embed the styles into the SVG document directly.

In order to do this, you manipulate the DOM to make the SVG element look like this:

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="100" version="1.1">
   <defs>
     <style>
       .rectangleStyle{
           width:200px;
           height:100px;
           stroke:black;
           stroke-width: 6;
           fill: green;
       }       
     </style>
   </defs>
   <rect class="rectangleStyle"/>
</svg>
Eyeless Whim
  • 273
  • 1
  • 2
  • 11