使用jspdf生成pdf报表
由于前台html已经动态生成报表,而且,前台有一个功能,一个daterange组件,当你拖动的时候,报表会在不提交到后台的情况下动态变化。
因此需要用到js生成生报表:
用到的组件:
jquery.js jspdf.js canvg.js html2canvas.js jspdf.plugin.autotable.js
前台动态生成的chart现在一般是用的html5的canvas或者是svg,很不幸运,我遇到的是svg,如果是flash没研究过。
由于报表还需要保持原html页面的外观,但是又不是整个html,真正需要转换成pdf报表的是:html+svg
前提:jsPDF支持html,但支持不是很好,当你用一个html直接生成pdf的时候,其实他只保留了html里面文本,样式,结构都丢失了。
比如:table就丢失了。
jsPDF不支持svg导入。
思路:将svg转换成canvas,再将html+canvas转换成canvas,再使用html2canvas将canvas转换成图片,最后将图片写入pdf.
table的话就使用:jspdf.plugin.autotable.js
firefox:html2canvas不能直接将svg+html转换成canvas -->先将svg元素转换成canvas-->html+canvas转换成canvas
chrome:html2canvas可以直接将svg+html转换成canvas
//将指定节点下面的所有svg转换成canvas
//这里需要:canvg.js
functionsvg2canvas(targetElem){
varnodesToRecover=[];
varnodesToRemove=[];
varsvgElem=targetElem.find('svg');
svgElem.each(function(index,node){
varparentNode=node.parentNode;
varsvg=node.outerHTML;
varcanvas=document.createElement('canvas');
canvg(canvas,svg);
nodesToRecover.push({
parent:parentNode,
child:node
});
parentNode.removeChild(node);
nodesToRemove.push({
parent:parentNode,
child:canvas
});
parentNode.appendChild(canvas);
});
}
//这里是将html(文本)在一个iframe里面打开
//主要是排除其它元素的干扰导致不成功,之前是一直输出不成功,所示才使用iframe
//这段代码是官网抠下来的。
//还有个问题就是:如果将页面的chart转换成canvas了,那web页面报表动态变化的功能将丢失。
functionopenWithIframe(html){
variframe=document.createElement('iframe');
iframe.setAttribute("id","myFrmame");
var$iframe=$(iframe);
$iframe.css({
'visibility':'hidden','position':'static','z-index':'4'
}).width($(window).width()).height($(window).height());
$('body').append(iframe);
varifDoc=iframe.contentWindow.document;
//这里做是将报表使用到的css重新写入到iframe中,根据自身的需要
varstyle="<linkhref='/javax.faces.resource/css/auth.css.jsf'rel='stylesheet'type='text/css'>";
style+="<linkhref='/javax.faces.resource/css/common.css.jsf'rel='stylesheet'type='text/css'>";
style+="<linkhref='/javax.faces.resource/css/dc.css.jsf'rel='stylesheet'type='text/css'>";
html="<!DOCTYPEhtml><html><head>"+style+"</head><body>"+html+"</body></html>"
ifDoc.open();
ifDoc.write(html);
ifDoc.close();
/*
//这里做一些微调,根据自身的需要
varfbody=$iframe.contents().find("body");
fbody.find("#chart-center").removeAttr("width");
fbody.find(".page-container").css("width","370px");
fbody.find(".center-container").css("width","600px");
fbody.find("#severity-chartsvg").attr("width","370");
fbody.find("#status-chartsvg").attr("width","300");
*/
returnfbody;
}
//导出pdf
functionexportAsPDF(){
//得到要导出pdf的html根节点
varchartCenter=document.getElementById("chart-center").outerHTML;
varfbody=openWithIframe(chartCenter);
svg2canvas(fbody);
//html2canvas官网的标准方法
html2canvas(fbody,{
onrendered:function(canvas){
//varmyImage=canvas.toDataURL("image/png");
//alert(myImage);
//window.open(myImage);
/*
canvas.toBlob(function(blob){
saveAs(blob,"report.png");
},"image/png");
*/
//将图片转换成:base64编码的jpg图片。
varimgData=canvas.toDataURL('image/jpeg');
//alert(imgData);
//l:横向,p:纵向
vardoc=newjsPDF('l','pt','a3');
//vardoc=newjsPDF('p','mm',[290,210]);
//vardoc=newjsPDF();//默认是A4,由于我的报表比较大,所以专门设置了尺寸。
doc.setFontSize(22);
doc.setFontType("bolditalic");
doc.text(500,30,"TicketReport");//x:500,y:30
doc.addImage(imgData,'jpeg',10,60);//写入位置:x:10,y:60
doc.addPage();//新建一页
//这里就是把将table写入到pdf里面。
varres=doc.autoTableHtmlToJson(document.getElementById("tickets-summary-table"),true);
doc.autoTable(res.columns,res.data);
doc.save('ticket.report_'+newDate().getTime()+'.pdf');
$('#myFrmame').remove();//最后将iframe删除
},
background:"#fff",//这里给生成的图片默认背景,不然的话,如果你的html根节点没有设置背景的话,会用黑色填充。
allowTaint:true//避免一些不识别的图片干扰,默认为false,遇到不识别的图片干扰则会停止处理html2canvas
});
};
以上所述就是本文的全部内容了,希望大家能够喜欢。