如何将带有大量svg图表的html转换为pdf?

时间:2021-09-03 13:07:12

I have a dashboard with lots of svg charts. I need to give a feature to export this entire html as a pdf.

我有一个带有大量svg图表的仪表板。我需要提供一个功能来将整个html导出为pdf。

I looked into few tools like phantomjs and htmltocanvas etc. But I am unable to convert svg into pdf or even images.

我查看了几个工具,如phantomjs和htmltocanvas等。但我无法将svg转换为pdf甚至图像。

I thought, may be using htmltocanvas I'll first convert html into png and then convert png into pdf using phantomjs.

我想,可能正在使用htmltocanvas我首先将html转换为png,然后使用phantomjs将png转换为pdf。

htmltocanvas converts rest of the html page into png but not the svg charts.

htmltocanvas将html页面的其余部分转换为png但不转换为svg图表。

Is there any better way or tools to do this?

有没有更好的方法或工具来做到这一点?

Below is the code to convert html to image.

下面是将html转换为图像的代码。

html2canvas($(".content"), {
            onrendered: function(canvas) {
                var img = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
                window.location.href = img;

            }
        });

and one of the SVG chart is as follows.

其中一个SVG图表如下。

<svg width="330" height="320" style="overflow: hidden;"><defs><clipPath id="c3-1462852070590-clip"><rect width="330" height="316"></rect></clipPath><clipPath id="c3-1462852070590-clip-xaxis"><rect x="-31" y="-20" width="392" height="20"></rect></clipPath><clipPath id="c3-1462852070590-clip-yaxis"><rect x="-29" y="-4" width="20" height="340"></rect></clipPath><clipPath id="c3-1462852070590-clip-grid"><rect width="330" height="316"></rect></clipPath><clipPath id="c3-1462852070590-clip-subchart"><rect width="330"></rect></clipPath></defs><g transform="translate(0.5,4.5)"><text class="c3-text c3-empty" text-anchor="middle" dominant-baseline="middle" x="165" y="158" style="opacity: 0;"></text><rect class="c3-zoom-rect" width="330" height="316" style="opacity: 0;"></rect><g clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip)" class="c3-regions" style="visibility: hidden;"></g><g clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip-grid)" class="c3-grid" style="visibility: hidden;"><g class="c3-xgrid-focus"><line class="c3-xgrid-focus" x1="-10" x2="-10" y1="0" y2="316" style="visibility: hidden;"></line></g></g><g clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip)" class="c3-chart"><g class="c3-event-rects c3-event-rects-single" style="fill-opacity: 0;"><rect class=" c3-event-rect c3-event-rect-0" x="0" y="0" width="330" height="316"></rect></g><g class="c3-chart-bars"><g class="c3-chart-bar c3-target c3-target-FS1" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-FS1 c3-bars c3-bars-FS1" style="cursor: pointer;"></g></g><g class="c3-chart-bar c3-target c3-target-FS2" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-FS2 c3-bars c3-bars-FS2" style="cursor: pointer;"></g></g><g class="c3-chart-bar c3-target c3-target-Renewal" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-Renewal c3-bars c3-bars-Renewal" style="cursor: pointer;"></g></g><g class="c3-chart-bar c3-target c3-target-Tele-sales" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-Tele-sales c3-bars c3-bars-Tele-sales" style="cursor: pointer;"></g></g></g><g class="c3-chart-lines"><g class="c3-chart-line c3-target c3-target-FS1" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-FS1 c3-lines c3-lines-FS1"></g><g class=" c3-shapes c3-shapes-FS1 c3-areas c3-areas-FS1"></g><g class=" c3-selected-circles c3-selected-circles-FS1"></g><g class=" c3-shapes c3-shapes-FS1 c3-circles c3-circles-FS1" style="cursor: pointer;"></g></g><g class="c3-chart-line c3-target c3-target-FS2" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-FS2 c3-lines c3-lines-FS2"></g><g class=" c3-shapes c3-shapes-FS2 c3-areas c3-areas-FS2"></g><g class=" c3-selected-circles c3-selected-circles-FS2"></g><g class=" c3-shapes c3-shapes-FS2 c3-circles c3-circles-FS2" style="cursor: pointer;"></g></g><g class="c3-chart-line c3-target c3-target-Renewal" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-Renewal c3-lines c3-lines-Renewal"></g><g class=" c3-shapes c3-shapes-Renewal c3-areas c3-areas-Renewal"></g><g class=" c3-selected-circles c3-selected-circles-Renewal"></g><g class=" c3-shapes c3-shapes-Renewal c3-circles c3-circles-Renewal" style="cursor: pointer;"></g></g><g class="c3-chart-line c3-target c3-target-Tele-sales" style="opacity: 1; pointer-events: none;"><g class=" c3-shapes c3-shapes-Tele-sales c3-lines c3-lines-Tele-sales"></g><g class=" c3-shapes c3-shapes-Tele-sales c3-areas c3-areas-Tele-sales"></g><g class=" c3-selected-circles c3-selected-circles-Tele-sales"></g><g class=" c3-shapes c3-shapes-Tele-sales c3-circles c3-circles-Tele-sales" style="cursor: pointer;"></g></g></g><g class="c3-chart-arcs" transform="translate(122.984375,158)"><text class="c3-chart-arcs-title" style="text-anchor: middle; opacity: 0;"></text><g class="c3-chart-arc c3-target c3-target-FS1"><g class=" c3-shapes c3-shapes-FS1 c3-arcs c3-arcs-FS1"><path class=" c3-shape c3-shape c3-arc c3-arc-FS1" transform="" d="M7.154090006472169e-15,-116.83515625A116.83515625,116.83515625 0 1,1 -107.89143050974987,44.831829747643916L0,0Z" style="fill: rgb(31, 119, 180); cursor: pointer; opacity: 1;"></path></g><text dy=".35em" class="" transform="translate(77.74499355097029,51.88454845881587)" style="opacity: 1; text-anchor: middle; pointer-events: none;">68.7%</text></g><g class="c3-chart-arc c3-target c3-target-FS2"><g class=" c3-shapes c3-shapes-FS2 c3-arcs c3-arcs-FS2"><path class=" c3-shape c3-shape c3-arc c3-arc-FS2" transform="" d="M-44.4439868873686,-108.0517735417486A116.83515625,116.83515625 0 0,1 -11.653578222643608,-116.25251760960121L0,0Z" style="fill: rgb(255, 140, 0); cursor: pointer; opacity: 1;"></path></g><text dy=".35em" class="" transform="translate(-22.67752725334393,-90.67535579576993)" style="opacity: 1; text-anchor: middle; pointer-events: none;"></text></g><g class="c3-chart-arc c3-target c3-target-Renewal"><g class=" c3-shapes c3-shapes-Renewal c3-arcs c3-arcs-Renewal"><path class=" c3-shape c3-shape c3-arc c3-arc-Renewal" transform="" d="M-107.89143050974987,44.831829747643916A116.83515625,116.83515625 0 0,1 -44.4439868873686,-108.0517735417486L0,0Z" style="fill: rgb(0, 128, 0); cursor: pointer; opacity: 1;"></path></g><text dy=".35em" class="" transform="translate(-86.32911494813567,-35.82700522353499)" style="opacity: 1; text-anchor: middle; pointer-events: none;">25.1%</text></g><g class="c3-chart-arc c3-target c3-target-Tele-sales"><g class=" c3-shapes c3-shapes-Tele-sales c3-arcs c3-arcs-Tele-sales"><path class=" c3-shape c3-shape c3-arc c3-arc-Tele-sales" transform="" d="M-11.653578222643608,-116.25251760960121A116.83515625,116.83515625 0 0,1 8.230819442412569e-14,-116.83515625L0,0Z" style="fill: rgb(214, 39, 40); cursor: pointer; opacity: 1;"></path></g><text dy=".35em" class="" transform="translate(-4.66725363658852,-93.35152454302703)" style="opacity: 1; text-anchor: middle; pointer-events: none;"></text></g></g><g class="c3-chart-texts"><g class="c3-chart-text c3-target c3-target-FS1" style="opacity: 1; pointer-events: none;"><g class=" c3-texts c3-texts-FS1"></g></g><g class="c3-chart-text c3-target c3-target-FS2" style="opacity: 1; pointer-events: none;"><g class=" c3-texts c3-texts-FS2"></g></g><g class="c3-chart-text c3-target c3-target-Renewal" style="opacity: 1; pointer-events: none;"><g class=" c3-texts c3-texts-Renewal"></g></g><g class="c3-chart-text c3-target c3-target-Tele-sales" style="opacity: 1; pointer-events: none;"><g class=" c3-texts c3-texts-Tele-sales"></g></g></g></g><g clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip-grid)" class="c3-grid c3-grid-lines"><g class="c3-xgrid-lines"></g><g class="c3-ygrid-lines"></g></g><g class="c3-axis c3-axis-x" clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip-xaxis)" transform="translate(0,316)" style="visibility: visible; opacity: 0;"><text class="c3-axis-x-label" transform="" x="330" dx="-0.5em" dy="-0.5em" style="text-anchor: end;"></text><g class="tick" transform="translate(165, 0)" style="opacity: 1;"><line y2="6" x1="0" x2="0"></line><text y="9" x="0" transform="" style="text-anchor: middle; display: block;"><tspan x="0" dy=".71em" dx="0">0</tspan></text></g><path class="domain" d="M0,6V0H330V6"></path></g><g class="c3-axis c3-axis-y" clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip-yaxis)" transform="translate(0,0)" style="visibility: visible; opacity: 0;"><text class="c3-axis-y-label" transform="rotate(-90)" x="0" dx="-0.5em" dy="1.2em" style="text-anchor: end;"></text><g class="tick" transform="translate(0,296)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">0</tspan></text></g><g class="tick" transform="translate(0,257)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">10</tspan></text></g><g class="tick" transform="translate(0,218)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">20</tspan></text></g><g class="tick" transform="translate(0,179)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">30</tspan></text></g><g class="tick" transform="translate(0,140)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">40</tspan></text></g><g class="tick" transform="translate(0,101)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">50</tspan></text></g><g class="tick" transform="translate(0,62)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">60</tspan></text></g><g class="tick" transform="translate(0,23)" style="opacity: 1;"><line x2="-6"></line><text x="-9" y="0" style="text-anchor: end;"><tspan x="-9" dy="3">70</tspan></text></g><path class="domain" d="M-6,1H0V316H-6"></path></g><g class="c3-axis c3-axis-y2" transform="translate(330,0)" style="visibility: hidden; opacity: 0;"><text class="c3-axis-y2-label" transform="rotate(-90)" x="0" dx="-0.5em" dy="-0.5em" style="text-anchor: end;"></text><g class="tick" transform="translate(0,316)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0</tspan></text></g><g class="tick" transform="translate(0,285)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.1</tspan></text></g><g class="tick" transform="translate(0,253)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.2</tspan></text></g><g class="tick" transform="translate(0,222)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.3</tspan></text></g><g class="tick" transform="translate(0,190)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.4</tspan></text></g><g class="tick" transform="translate(0,159)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.5</tspan></text></g><g class="tick" transform="translate(0,127)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.6</tspan></text></g><g class="tick" transform="translate(0,96)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.7</tspan></text></g><g class="tick" transform="translate(0,64)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.8</tspan></text></g><g class="tick" transform="translate(0,33)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">0.9</tspan></text></g><g class="tick" transform="translate(0,1)" style="opacity: 1;"><line x2="6" y2="0"></line><text x="9" y="0" style="text-anchor: start;"><tspan x="9" dy="3">1</tspan></text></g><path class="domain" d="M6,1H0V316H6"></path></g></g><g transform="translate(0.5,320.5)" style="visibility: hidden;"><g clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip-subchart)" class="c3-chart"><g class="c3-chart-bars"></g><g class="c3-chart-lines"></g></g><g clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip)" class="c3-brush" style="pointer-events: all; -webkit-tap-highlight-color: rgba(0, 0, 0, 0);"><rect class="background" x="0" width="330" style="visibility: hidden; cursor: crosshair;"></rect><rect class="extent" x="0" width="0" style="cursor: move;"></rect><g class="resize e" transform="translate(0,0)" style="cursor: ew-resize; display: none;"><rect x="-3" width="6" height="6" style="visibility: hidden;"></rect></g><g class="resize w" transform="translate(0,0)" style="cursor: ew-resize; display: none;"><rect x="-3" width="6" height="6" style="visibility: hidden;"></rect></g></g><g class="c3-axis-x" transform="translate(0,0)" clip-path="url(http://localhost:8080/charts/dashboard?operation=getUserDashBoard&amp;t=dashboardMenuOption#c3-1462852070590-clip-xaxis)" style="opacity: 0;"><g class="tick" transform="translate(165, 0)" style="opacity: 1;"><line y2="6" x1="0" x2="0"></line><text y="9" x="0" transform="" style="text-anchor: middle; display: block;"><tspan x="0" dy=".71em" dx="0">0</tspan></text></g><path class="domain" d="M0,6V0H330V6"></path></g></g><g transform="translate(258.2671875,0)"><g class=" c3-legend-item c3-legend-item-FS1" style="visibility: visible; cursor: pointer;"><text x="14" y="131" style="pointer-events: none;">FS1</text><rect class="c3-legend-item-event" x="0" y="117" width="43.296875" height="19" style="fill-opacity: 0;"></rect><rect class="c3-legend-item-tile" x="0" y="122" width="10" height="10" style="pointer-events: none; fill: rgb(31, 119, 180);"></rect></g><g class=" c3-legend-item c3-legend-item-FS2" style="visibility: visible; cursor: pointer; opacity: 1;"><text x="14" y="150" style="pointer-events: none;">FS2</text><rect class="c3-legend-item-event" x="0" y="136" width="43.296875" height="19" style="fill-opacity: 0;"></rect><rect class="c3-legend-item-tile" x="0" y="141" width="10" height="10" style="pointer-events: none; fill: darkorange;"></rect></g><g class=" c3-legend-item c3-legend-item-Renewal" style="visibility: visible; cursor: pointer; opacity: 1;"><text x="14" y="169" style="pointer-events: none;">Renewal</text><rect class="c3-legend-item-event" x="0" y="155" width="68.25" height="19" style="fill-opacity: 0;"></rect><rect class="c3-legend-item-tile" x="0" y="160" width="10" height="10" style="pointer-events: none; fill: green;"></rect></g><g class=" c3-legend-item c3-legend-item-Tele-sales" style="visibility: visible; cursor: pointer; opacity: 1;"><text x="14" y="188" style="pointer-events: none;">Tele sales</text><rect class="c3-legend-item-event" x="0" y="174" width="74.03125" height="19" style="fill-opacity: 0;"></rect><rect class="c3-legend-item-tile" x="0" y="179" width="10" height="10" style="pointer-events: none; fill: rgb(214, 39, 40);"></rect></g></g></svg>

There are many more such charts on a single html page.

单个html页面上还有更多这样的图表。

1 个解决方案

#1


0  

Here's PhantomJS code that works for the SVG you provided (version 2.1.1).

这是适用于您提供的SVG(版本2.1.1)的PhantomJS代码。

var link = "http://example.com/svg.html";
var page = require('webpage').create();
var system = require('system');

page.settings.userAgent = 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0';
page.viewportSize = { width: 1280, height: 720 };

page.onError = function(msg, trace) {

  var msgStack = ['ERROR: ' + msg];

  if (trace && trace.length) {
    msgStack.push('TRACE:');
    trace.forEach(function(t) {
      msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
    });
  }

  console.error(msgStack.join('\n'));

};

page.onConsoleMessage = function(msg, lineNum, sourceId) {
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};

page.open(link, function(status) {

    console.log(status);

    // Give it time to load
    setTimeout(function(){ 
        page.render("svg.png");
        page.render("svg.pdf");
        phantom.exit(); 
    }, 3000);

});

#1


0  

Here's PhantomJS code that works for the SVG you provided (version 2.1.1).

这是适用于您提供的SVG(版本2.1.1)的PhantomJS代码。

var link = "http://example.com/svg.html";
var page = require('webpage').create();
var system = require('system');

page.settings.userAgent = 'Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0';
page.viewportSize = { width: 1280, height: 720 };

page.onError = function(msg, trace) {

  var msgStack = ['ERROR: ' + msg];

  if (trace && trace.length) {
    msgStack.push('TRACE:');
    trace.forEach(function(t) {
      msgStack.push(' -> ' + t.file + ': ' + t.line + (t.function ? ' (in function "' + t.function +'")' : ''));
    });
  }

  console.error(msgStack.join('\n'));

};

page.onConsoleMessage = function(msg, lineNum, sourceId) {
    console.log('CONSOLE: ' + msg + ' (from line #' + lineNum + ' in "' + sourceId + '")');
};

page.open(link, function(status) {

    console.log(status);

    // Give it time to load
    setTimeout(function(){ 
        page.render("svg.png");
        page.render("svg.pdf");
        phantom.exit(); 
    }, 3000);

});