使用jspdf生成pdf报表


Posted in Javascript onJuly 03, 2015

由于前台html已经动态生成报表,而且,前台有一个功能,一个date range组件,当你拖动的时候,报表会在不提交到后台的情况下动态变化。
因此需要用到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
function svg2canvas (targetElem) {
  var nodesToRecover = [];
  var nodesToRemove = [];

  var svgElem = targetElem.find('svg');

  svgElem.each(function(index, node) {
    var parentNode = node.parentNode;
    
    var svg = node.outerHTML;

    var canvas = 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页面报表动态变化的功能将丢失。
function openWithIframe(html){
    
  var iframe = 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);
  
  
  var ifDoc = iframe.contentWindow.document;
  
//这里做是将报表使用到的css重新写入到iframe中,根据自身的需要
  var style = "<link href='/javax.faces.resource/css/auth.css.jsf' rel='stylesheet' type='text/css'>";
  style+="<link href='/javax.faces.resource/css/common.css.jsf' rel='stylesheet' type='text/css'>";
  style+="<link href='/javax.faces.resource/css/dc.css.jsf' rel='stylesheet' type='text/css'>";
  
  html = "<!DOCTYPE html><html><head>"+style+"</head><body>"+html+"</body></html>"
  
  ifDoc.open();    
  ifDoc.write(html);    
  ifDoc.close();
  
  /*
  //这里做一些微调,根据自身的需要
  var fbody = $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-chart svg").attr("width", "370");
  fbody.find("#status-chart svg").attr("width", "300");
  */
  return fbody;
}
//导出pdf
function exportAsPDF(){
  //得到要导出pdf的html根节点  
  var chartCenter = document.getElementById("chart-center").outerHTML;
  
  var fbody = openWithIframe(chartCenter);
  svg2canvas(fbody);
  
  //html2canvas官网的标准方法
  html2canvas(fbody, {
    onrendered: function(canvas) {
      //var myImage = canvas.toDataURL("image/png");
      //alert(myImage);
      //window.open(myImage);
      
      /*
      canvas.toBlob(function(blob) {
        saveAs(blob, "report.png");
      }, "image/png");
      */
      
      //将图片转换成:base64编码的jpg图片。
      var imgData = canvas.toDataURL('image/jpeg');
      //alert(imgData);
            
      //l:横向, p:纵向
      var doc = new jsPDF('l', 'pt', 'a3');
      //var doc = new jsPDF('p', 'mm', [290, 210]);
      //var doc = new jsPDF();//默认是A4,由于我的报表比较大,所以专门设置了尺寸。
      doc.setFontSize(22);
      doc.setFontType("bolditalic");
      doc.text(500, 30, "Ticket Report"); //x:500, y:30
      
      doc.addImage(imgData, 'jpeg', 10, 60); //写入位置:x:10, y:60
      
      doc.addPage();  //新建一页
      
      //这里就是把将table写入到pdf里面。
      var res = doc.autoTableHtmlToJson(document.getElementById("tickets-summary-table"), true);
      doc.autoTable(res.columns, res.data);
      
      doc.save('ticket.report_'+new Date().getTime()+'.pdf');
      $('#myFrmame').remove(); //最后将iframe删除
    },
    background:"#fff", //这里给生成的图片默认背景,不然的话,如果你的html根节点没有设置背景的话,会用黑色填充。
    allowTaint: true  //避免一些不识别的图片干扰,默认为false,遇到不识别的图片干扰则会停止处理html2canvas
  });
  
};

以上所述就是本文的全部内容了,希望大家能够喜欢。

Javascript 相关文章推荐
js中点击空白区域时文本框与隐藏层的显示与影藏问题
Aug 26 Javascript
js中判断对象是否为空的三种实现方法
Dec 23 Javascript
javascript 获取元素样式必杀技
May 04 Javascript
深入理解JavaScript系列(21):S.O.L.I.D五大原则之接口隔离原则ISP详解
Mar 05 Javascript
深入浅析JavaScript中prototype和proto的关系
Nov 15 Javascript
实例详解jQuery表单验证插件validate
Jan 18 Javascript
详解AngularJS过滤器的使用
Mar 11 Javascript
jQuery改变form表单的action,并进行提交的实现代码
May 25 Javascript
vue2中filter()的实现代码
Jul 09 Javascript
微信小程序实现多选框全选与取消全选功能示例
May 14 Javascript
微信小程序canvas开发水果老虎机的思路详解
Feb 07 Javascript
JQuery Ajax如何实现注册检测用户名
Sep 25 jQuery
JSON相关知识汇总
Jul 03 #Javascript
javascript表格的渲染组件
Jul 03 #Javascript
解决jquery实现的radio重新选中的问题
Jul 03 #Javascript
移动端JQ插件hammer使用详解
Jul 03 #Javascript
jQuery+AJAX实现无刷新下拉加载更多
Jul 03 #Javascript
Javascript实现字数统计
Jul 03 #Javascript
JavaScript获取表格(table)当前行的值、删除行、增加行
Jul 03 #Javascript
You might like
曾在DC漫画界反派角色扮演的演员,谁才是你心目中的小丑之王?
2020/04/09 欧美动漫
yii2中结合gridview如何使用modal弹窗实例代码详解
2016/06/12 PHP
PHP基于自增数据如何生成不重复的随机数示例
2017/05/19 PHP
jquery中获取元素的几种方式小结
2011/07/05 Javascript
sencha touch 模仿tabpanel导航栏TabBar的实例代码
2013/10/24 Javascript
详解addEventListener的三个参数之useCapture
2015/03/16 Javascript
纯javascript判断查询日期是否为有效日期
2015/08/24 Javascript
JavaScript的Ext JS框架中的GridPanel组件使用指南
2016/05/21 Javascript
简单分析javascript中的函数
2016/09/10 Javascript
js操作浏览器的参数方法
2017/01/21 Javascript
深入理解javascript的getTime()方法
2017/02/16 Javascript
浅谈Vue服务端渲染框架Nuxt的那些事
2018/12/21 Javascript
解决vue项目刷新后,导航菜单高亮显示的位置不对问题
2019/11/01 Javascript
JavaScript动态生成表格的示例
2020/11/02 Javascript
[15:41]教你分分钟做大人——灰烬之灵
2015/03/11 DOTA
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
跟老齐学Python之用while来循环
2014/10/02 Python
Python中使用socket发送HTTP请求数据接收不完整问题解决方法
2015/02/04 Python
Python使用Flask框架获取当前查询参数的方法
2015/03/21 Python
python中异常捕获方法详解
2017/03/03 Python
Python基于递归算法实现的走迷宫问题
2017/08/04 Python
Python+tkinter使用40行代码实现计算器功能
2018/01/30 Python
pandas取出重复数据的方法
2019/07/04 Python
python argparse传入布尔参数false不生效的解决
2020/04/20 Python
python正则表达式的懒惰匹配和贪婪匹配说明
2020/07/13 Python
python 实现图片批量压缩的示例
2020/12/18 Python
canvas里面如何基于随机点绘制一个多边形的方法
2018/06/13 HTML / CSS
AmazeUI 点击元素显示全屏的实现
2020/08/25 HTML / CSS
Argos官网:英国家喻户晓的百货零售连锁商
2017/04/03 全球购物
自我评价如何写好?
2014/01/05 职场文书
小学生环保倡议书
2014/05/15 职场文书
企业读书活动总结
2014/06/30 职场文书
党员四风问题个人对照检查材料
2014/10/26 职场文书
运动会广播稿200字
2015/08/19 职场文书
学术会议开幕词
2016/03/03 职场文书
解析mybatis-plus中的resultMap简单使用
2021/11/23 Java/Android