简体   繁体   English

使用多个谷歌图表和jspdf生成PDF

[英]Generating PDF using multiple google charts and jspdf

Adding to this stackoverflow question: Generating pdf using multiple graphs using html2canvas and jspdf添加到这个 stackoverflow 问题: 使用 html2canvas 和 jspdf 使用多个图形生成 pdf

I have tried to use the Promise javascript api as follows:我尝试使用 Promise javascript api 如下:

function GeneratePDFforCharts(divNamesForPDF)
{


var arrayOfPromises = [];

//Note: Checking if the browser supports Promises
if (window.Promise) {

    for (var i = 0; i < divNamesForPDF.length; i++)
    {
        var promise = new Promise(function (resolve, reject) {
            //asynchronous code goes here
            //Note: The Promise is passed a callback function. The callback takes two arguments, resolve and reject.
            //Note: If everything is successful, the promise is fullfilled by calling resolve(). In case of an error, reject() is called with an Error object.
            var element = $(divNamesForPDF[i]).get(0);
            html2canvas(element, {
                onrendered: function (canvas) {
                    resolve(canvas.toDataURL('image/png'));
                }
            });
        });
        arrayOfPromises.push(promise);
    }

    Promise.all(arrayOfPromises).then(function (canvases) {
        var count = 0;
        var pageNumber = 1;

        var doc = new jsPDF('l', 'mm', [297, 210], true); //true is set for pdf compression

        for (var i = 0; i < canvases.length; i++)
        {
            if (isOdd(count)) //2nd chart
            {
                doc.addImage(canvases[i], 'PNG', 10, 105, 270, 100, null, 'FAST'); //x, y, width, height - FAST is used for png compression
                var pageNo = pageNumber.toString();
                doc.text(140, 207, pageNo); //x, y, text
                pageNumber++;
            }
            else //1st chart
            {
                if (count != 0)
                {
                    doc.addPage();
                }
                doc.addImage(canvases[i], 'PNG', 10, 5, 270, 100, null, 'FAST');
            }
            count++;
        }

        doc.save('IEA_Global_MonthlyStocks_Analytics.pdf');
    });

}

}

What I am doing is sending 33 divnames representing google chart panels as a parameter for the jspdf to generate the pdf.我正在做的是发送 33 个 divnames 代表谷歌图表面板作为 jspdf 生成 pdf 的参数。

Problem: However, the Chrome browser is crashing when clicking on the generate pdf button.问题:但是,Chrome 浏览器在单击生成 pdf 按钮时崩溃。 After debugging it seems that it is passing the for loop.经过调试,它似乎正在传递 for 循环。 However it never goes in the Promise.all function.但是它永远不会出现在 Promise.all 函数中。

Also, it is good to point out the following:此外,最好指出以下几点:

  1. When I just pass 4 divs for example, the pdf is generated successfully.例如,当我只传递 4 个 div 时,成功生成了 pdf。 So it is a matter of chrome not handling that amount of base 64s being generated?所以这是铬不处理生成的基本 64 数量的问题?
  2. I used the 'FAST' parameter when adding image to pdf so as to make it compressed aswell.我在将图像添加到 pdf 时使用了“FAST”参数,以便将其压缩。

Any feedback on this?对此有任何反馈吗? Am I doing something wrong please?请问我做错了吗?

It seems that the code works but doesn't scale too well.代码似乎有效,但扩展性不太好。

It's possible that by performing all operations in parallel, javascript's Garbage Collection (GC) isn't given the opportunity to clear intermediate objects, and an oversized heap causes the crash.有可能通过并行执行所有操作,javascript 的垃圾收集 (GC) 没有机会清除中间对象,并且过大的堆会导致崩溃。

Performing the operations in series may have a positive effect.依次执行这些操作可能会产生积极的影响。 The code is simply derived from the code in the question.该代码只是从问题中的代码派生而来。

First, an adaptor function, which promisifies html2canvas() :首先,一个适配器函数,它承诺html2canvas()

function html2canvasAsync(element) {
    return new Promise(function(resolve, reject) {
        html2canvas(element, {
            onrendered: function (canvas) {
                resolve(canvas.toDataURL('image/png'));
            }
        });
    });
};

Now call divNamesForPDF.reduce(...) to serialize the asynchronous operations and progressively add to the jsPDF doc :现在调用divNamesForPDF.reduce(...)来序列化异步操作并逐步添加到 jsPDF doc

function GeneratePDFforCharts(divNamesForPDF) {
    if (window.Promise) {
        var doc = new jsPDF('l', 'mm', [297, 210], true); //true is set for pdf compression
        return divNamesForPDF.reduce(function(p, name, i) {
            return p.then(function(pageNumber) {
                return html2canvasAsync($(name).get(0)) // or `document.getElementById(name)` ?
                // return html2canvasAsync(document.getElementById(name)) // possibly?
                .then(function(canvas) {
                    if (isOdd(i)) { // odds
                        doc.addImage(canvas, 'PNG', 10, 105, 270, 100, null, 'FAST'); //x, y, width, height - FAST is used for png compression
                        doc.text(140, 207, pageNumber.toString()); //x, y, text
                        pageNumber++;
                    } else { // evens
                        if (i > 0) {
                            doc.addPage();
                        }
                        doc.addImage(canvas, 'PNG', 10, 5, 270, 100, null, 'FAST');
                    }
                    return pageNumber;
                }).catch(function(e) {
                    // Error handling is a good idea
                    console.log(e);
                    doc.text(35, 25, e.message); // possibly add the error message to doc
                });
            });
        }, Promise.resolve(1)) // starter promise resolved with page number 1
        .then(function() {
            doc.save('IEA_Global_MonthlyStocks_Analytics.pdf');
        });
    }
}

checked only for syntax只检查语法

As I say, it's no better than "possible" that this will fix the issue.正如我所说,这不会比“可能”更好地解决问题。 It won't cost anything to give it a try.尝试它不会花费任何费用。 The worst that might happen is another Chrome crash.可能发生的最糟糕的情况是另一次 Chrome 崩溃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM