bpampuch / pdfmake

Client/server side PDF printing in pure JavaScript
http://pdfmake.org
Other
11.62k stars 2.04k forks source link

PDF Charts #663

Open zacnewnham opened 8 years ago

zacnewnham commented 8 years ago

I am using pdfmake and I am trying to include graphs into the PDF output. The charts need to be created by using variables. I'm trying to create a bar chart, pie chart and line charts. Is there a solution for this?

sharvesh commented 8 years ago

+1

eldesgonzales commented 7 years ago

What kind of of chart did you use? I used https://jtblin.github.io/angular-chart.js/ and it worked fine. Did you convert your graphs into .toDataURL() ?

This is my code for getting my graph:

var canvas = $(".container #bar").get(0);
var dataURL = canvas.toDataURL();

generatePDF (dataURL);

For me ,the first thing to do is to try getting your chart like this: console.log($(".container #bar").get(0).toDataURL()); If you see a very long line, try to get it, and open it on another tab, if nothing has been shown, then try it on another class/id where the chart is. I can't explain further since I just did trial and error on getting the chart data.

bhericher commented 7 years ago

I don't know if it can help, but I have charts in SVG format : I convert them in png and then I can include them as image in the pdf. As the conversion is asynchronous, one must just take care to use a Promise.

jwerre commented 7 years ago

I think the solution for this would be to add support for SVG paths like PDFKit. Something like:

content = [{
    canvas: [
        {
            type: 'svg'
            path: 'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90'
        }
    ]
}];

... then you could use virtually any chart library you want.

Here's an example of how you might draw a pie chart with Paths.js:

let pie = require('paths-js/pie')

var content = [{
    canvas: []
 }];

var chart = pie({
  data: [
    {
      name: 'Italy',
      population: 59859996
    }, {
      name: 'Mexico',
      population: 118395054
    }, {
      name: 'France',
      population: 65806000
    }, {
      name: 'Argentina',
      population: 40117096
    }, {
      name: 'Japan',
      population: 127290000
    }
  ],
  accessor: function(x) {
    return x.population;
  },
  compute: {
    color: function(i) {
      return chartColors[i];
    }
  },
  center: [20, 15],
  r: 30,
  R: 50
});

chart.curves.forEach( function(curve, index) {
    content[0].canvas[index] = {
      type: 'svg',
      path: curve.sector.path.print()
    };
});

    console.log(content)
/*
[ { canvas: 
     [ { type: 'svg',
         path: 'M 20 -35 A 50 50 0 0 1 59.599813 -15.526297 L 43.759888 -3.315778 A 30 30 0 0 0 20 -15 Z ' },
       { type: 'svg',
         path: 'M 59.599813 -15.526297 A 50 50 0 0 1 40.370176 60.662412 L 32.222106 42.397447 A 30 30 0 0 0 43.759888 -3.315778 Z ' },
       { type: 'svg',
         path: 'M 40.370176 60.662412 A 50 50 0 0 1 -7.620771 56.678448 L 3.427537 40.007069 A 30 30 0 0 0 32.222106 42.397447 Z ' },
       { type: 'svg',
         path: 'M -7.620771 56.678448 A 50 50 0 0 1 -26.562961 33.217867 L -7.937776 25.93072 A 30 30 0 0 0 3.427537 40.007069 Z ' },
       { type: 'svg',
         path: 'M -26.562961 33.217867 A 50 50 0 0 1 20 -35 L 20 -15 A 30 30 0 0 0 -7.937776 25.93072 Z ' } ] } ]
*/
liborm85 commented 7 years ago

Added experimental path vector type with svg syntax support by commit https://github.com/bpampuch/pdfmake/commit/46ee6b440bd57f4a096e9f52eca49a4d5d32aff0.

Example of usage:

var dd = {
    content: [
        {
            canvas: [
                {
                    type: 'path',
                    d: 'M 0,20 L 100,160 Q 130,200 150,120 C 190,-40 200,200 300,150 L 400,90',
                    dash: {length: 5},
                    // lineWidth: 10,
                    lineColor: 'blue',
                },
             ]
        }
    ]
}
jwerre commented 5 years ago

Do you think it would be worth setting up a native chart implementation? Something like this:

{
    chart: 'pie',
    data: [10, 20, 30, 40],
    colors: ['red', 'green', 'blue', 'black'],
    position: [X, Y],
    size: [W, H]
}

I'd be happy to contribute and set this up the following:

mcanyucel commented 4 years ago

Well after 4 years of the opening of this topic, I would be happy just for a simple line chart .

drummerjolev commented 3 years ago

+1 charts would be an amazing addition

tulipdata-nathanbrunkard commented 3 years ago

I've had success using echarts Build a chart and then use the dataURL with an {image} field

const getChartDataUrl = ( option, w, h ) => new Promise(done => {
    const canvas = document.createElement('canvas')
    canvas.width = w || 600
    canvas.height = h || 200

    const chart = echarts.init(canvas)
    chart.setOption(option)
    chart.on('finished', () => done( chart.getDataURL() ))
})
//Returns a data url (promise): "data:image/png;base64,..."
codeion commented 2 years ago

https://echarts.apache.org/handbook/en/basics/release-note/5-3-0/#server-side-rendering-with-zero-dependencies

jaguarxii commented 2 years ago

Hi, I would like to add another option which worked for me (server-side):

It is worth noting that client-side libraries are easier to find, I worked with Plotly which also renders SVG charts which can be placed directly in the document definition.

UPDATE: I found Apache ECharts for js, and I am using it cause it is very simple its use and supports SVG rendering.