使用多个 google 图表和 jspdf 生成 PDF
Generating PDF using multiple google charts and jspdf
添加到这个 Whosebug 问题:
我尝试使用 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');
});
}
}
我正在做的是发送代表 google 图表面板的 33 个 divnames 作为 jspdf 生成 pdf 的参数。
问题:但是,Chrome 浏览器在单击生成 pdf 按钮时崩溃。调试后似乎它正在通过 for 循环。但是它永远不会出现在 Promise.all 函数中。
另外,指出以下几点也很好:
- 比如我只传了4个div,pdf就生成成功了。所以这是 chrome 不处理生成的 base 64 数量的问题?
- 我在将图像添加到 pdf 时使用了 'FAST' 参数以使其也被压缩。
对此有任何反馈吗?请问我做错了什么吗?
代码似乎可以工作,但扩展性不太好。
通过并行执行所有操作,javascript 的垃圾收集 (GC) 可能没有机会清除中间对象,并且过大的堆会导致崩溃。
执行一系列操作可能会产生积极的效果。代码只是简单地从问题中的代码导出。
首先,一个适配器函数,它承诺 html2canvas()
:
function html2canvasAsync(element) {
return new Promise(function(resolve, reject) {
html2canvas(element, {
onrendered: function (canvas) {
resolve(canvas.toDataURL('image/png'));
}
});
});
};
现在调用 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');
});
}
}
仅检查语法
正如我所说,这并不比 "possible" 更能解决问题。尝试一下不会花费任何费用。可能发生的最坏情况是另一次 Chrome 崩溃。
添加到这个 Whosebug 问题:
我尝试使用 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');
});
}
}
我正在做的是发送代表 google 图表面板的 33 个 divnames 作为 jspdf 生成 pdf 的参数。
问题:但是,Chrome 浏览器在单击生成 pdf 按钮时崩溃。调试后似乎它正在通过 for 循环。但是它永远不会出现在 Promise.all 函数中。
另外,指出以下几点也很好:
- 比如我只传了4个div,pdf就生成成功了。所以这是 chrome 不处理生成的 base 64 数量的问题?
- 我在将图像添加到 pdf 时使用了 'FAST' 参数以使其也被压缩。
对此有任何反馈吗?请问我做错了什么吗?
代码似乎可以工作,但扩展性不太好。
通过并行执行所有操作,javascript 的垃圾收集 (GC) 可能没有机会清除中间对象,并且过大的堆会导致崩溃。
执行一系列操作可能会产生积极的效果。代码只是简单地从问题中的代码导出。
首先,一个适配器函数,它承诺 html2canvas()
:
function html2canvasAsync(element) {
return new Promise(function(resolve, reject) {
html2canvas(element, {
onrendered: function (canvas) {
resolve(canvas.toDataURL('image/png'));
}
});
});
};
现在调用 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');
});
}
}
仅检查语法
正如我所说,这并不比 "possible" 更能解决问题。尝试一下不会花费任何费用。可能发生的最坏情况是另一次 Chrome 崩溃。