3

I am using css2pdf for saving my svg chart to pdf after onclick event. It works nicely for plotly.js, but not for c3.js - please see my fiddle: http://jsfiddle.net/3hs7cs4f/

I am sure it has to do something with the c3.js svg properties, but I have no idea how to solve this.

Here is the code:

<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet" />
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="http://www.cloudformatter.com/Resources/Pages/CSS2Pdf/Scrip /xeponline.jqplugin.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
</head>

<body>
<br><br>
  <!-- Source and on-click event for plotly.js -->
  <div id="plotly_chart" style="width: 90%; height: 270px"></div>
  <button onclick="return xepOnline.Formatter.Format('plotly_chart',{pageWidth:'11in', pageHeight:'8.5in',render:'download', srctype:'svg'});">Get plotly_PDF</button>

  <!-- Source and on-click event for c3.js-->
  <div id="c3_chart" style="width: 90%; height: 270px"></div>
  <button onclick="return xepOnline.Formatter.Format('c3_chart',{pageWidth:'11in', pageHeight:'8.5in',render:'download', srctype:'svg'});">Get c3_PDF</button>

<!-- JAVASCRIPT for plotly.js chart -->
<script type="text/javascript">
  Chart = document.getElementById('plotly_chart');

 Plotly.plot( Chart, [{
   x: [1, 2, 3, 4, 5],
   y: [1, 2, 4, 8, 16] }], { 
   margin: { t: 0 } } );
</script>

<!-- JAVASCRIPT for j3.js chart -->
<script type="text/javascript">
   var chart = c3.generate({
   bindto: '#c3_chart',
   padding: {
       top: 10,
       right: 70,
       bottom: 50,
       left: 75,
   },
   data: {
       columns: [
           ['data1', 100, 200, 150, 300, 200],
           ['data2', 400, 500, 250, 700, 300],
       ]
   }});
</script>

I tried a lot of other ways to save my c3.js charts, but none of them worked satisfyingly. The only thing that works is the ng-c3 exporter from annatomka, which uses the AngularJS module (https://github.com/annatomka/ng-c3-export). However, this one does not handle all of the css settings in my hands, and the quality of the downloaded png is limited by screen resolution. Thus, I really would like to go for a pdf exporter, and the one I found that handles all the css settings is css2pdf. But any other suggestions how to save c3 chart as pdf that work are also much appreciated. Thanks for the help!

schustischuster
  • 743
  • 9
  • 29
  • I figured out that when I leave out the "srctype:'svg'" attribute from the c3_chart xepOnline.Formatter.Format settings, css2pdf converts my c3.js svg, but the resulting pdf is empty with always 2kb size independently of the original svg dimensions. See updated fiddle http://jsfiddle.net/3hs7cs4f/1/ - so there is definitely something going on (wrong) with the c3.js svg properties. – schustischuster Jun 27 '17 at 01:01
  • 1
    Check the svg in the DOM and see if it is missing the namespace. If it is then you need to add it after the chart draws – Kevin Brown Jun 27 '17 at 16:54
  • I can see the following difference between the svg element from plotly.js, which works for css2pdf, and the svg element from c3.js, which doesn't work: plotly (class: main-svg; xmlns: http://www.w3.org/2000/svg; xmlns:xlink: http://www.w3.org/1999/xlink) C3 (class: overflow: hidden; no xmlns and xmlns:xlink defined) - does that help? – schustischuster Jun 27 '17 at 17:51
  • Yes, answer with working fiddle below – Kevin Brown Jun 27 '17 at 18:02
  • Very nice, Kevin. Thank you! – schustischuster Jun 28 '17 at 01:01

1 Answers1

5

As I suspected in the comment above, the SVG drawn by c3 lacks the SVG namespace. Css2PDF requires that SVG's be in this namespace.

See http://www.cloudformatter.com/CSS2Pdf.APIDoc.FAQ , first FAQ as it is the number one question asked.

To solve this issue, I added a little hack to inject the namespace attribute to this plot before print. There are better ways I am sure but this fiddle shows your result working.

<script>
   function addnsandprint(){
     $('#c3_chart').find('svg').attr('xmlns','http://www.w3.org/2000/svg');
     xepOnline.Formatter.Format('c3_chart',{pageWidth:'11in', 
        pageHeight:'8.5in',render:'download', srctype:'svg'});
   }
</script>

Fiddle: http://jsfiddle.net/3hs7cs4f/9/

Result:

enter image description here

NOTE: If your SVG makes use of xlink, you would also need to add the "xmlns:xlink" attribute of "http://www.w3.org/1999/xlink". For safe formatting, I would add both in your code.

Kevin Brown
  • 8,805
  • 2
  • 20
  • 38