使用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控件
May 07 Javascript
JS.GetAllChild(element,deep,condition)使用介绍
Sep 21 Javascript
JS按回车键实现登录的方法
Aug 25 Javascript
jQuery prototype冲突的2种解决方法(附demo示例下载)
Jan 21 Javascript
AngularJS中watch监听用法分析
Nov 04 Javascript
微信小程序 122100版本更新问题解决方案
Dec 22 Javascript
微信小程序实现图片自适应(支持多图)
Jan 25 Javascript
CSS3+JavaScript实现翻页幻灯片效果
Jun 28 Javascript
Vue.js实现网格列表布局转换方法
Aug 25 Javascript
vue-cli项目修改文件热重载失效的解决方法
Sep 19 Javascript
Nuxt 嵌套路由nuxt-child组件用法(父子页面组件的传值)
Nov 05 Javascript
Vue vee-validate插件的简单使用
Jun 22 Vue.js
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
超级简单的php+mysql留言本源码
2009/11/11 PHP
解析argc argv在php中的应用
2013/06/24 PHP
PHP实现文件下载详解
2014/11/27 PHP
php集成动态口令认证
2016/07/21 PHP
PHP PDOStatement::getColumnMeta讲解
2019/02/01 PHP
静态的动态续篇之来点XML
2006/08/15 Javascript
得到文本框选中的文字,动态插入文字的js代码
2007/03/07 Javascript
javascript中获取选中对象的类型
2007/04/02 Javascript
jsTree 基于JQuery的排序节点 Bug
2011/07/26 Javascript
js向上无缝滚动,网站公告效果 具体代码
2013/11/18 Javascript
jquery自定义滚动条插件示例分享
2014/02/21 Javascript
jQuery中toggleClass()方法用法实例
2015/01/05 Javascript
BootStrap 下拉菜单点击之后不会出现下拉菜单(下拉菜单不弹出)的解决方案
2016/12/14 Javascript
js原生Ajax的封装和原理详解
2017/03/11 Javascript
理解 javascript 中的函数表达式与函数声明
2017/07/07 Javascript
JavaScript获取tr td 的三种方式全面总结(推荐)
2017/08/15 Javascript
详解在vue-cli项目下简单使用mockjs模拟数据
2018/10/19 Javascript
layui监听工具栏的实例(操作列表按钮)
2019/09/10 Javascript
一篇文章带你浅入webpack的DLL优化打包
2020/02/20 Javascript
[04:55]完美世界副总裁蔡玮:DOTA2的自由、公平与信任
2013/12/18 DOTA
python根据开头和结尾字符串获取中间字符串的方法
2015/03/26 Python
使用IPython下的Net-SNMP来管理类UNIX系统的教程
2015/04/15 Python
详解python开发环境搭建
2016/12/16 Python
TensorFlow实现Softmax回归模型
2018/03/09 Python
python实现中文文本分句的例子
2019/07/15 Python
keras使用Sequence类调用大规模数据集进行训练的实现
2020/06/22 Python
15个应该掌握的Jupyter Notebook使用技巧(小结)
2020/09/23 Python
W Concept美国:精选全球独立设计师
2017/02/22 全球购物
英国最大的网上药品商店:Chemist Direct
2017/12/16 全球购物
会计与审计毕业生自荐信范文
2013/12/30 职场文书
医院学雷锋活动策划方案
2014/02/15 职场文书
工程部文员岗位职责
2015/02/04 职场文书
教师师德表现自我评价
2015/03/05 职场文书
教你利用Selenium+python自动化来解决pip使用异常
2021/05/20 Python
如何在C++中调用Python
2021/05/21 Python
Python与C++中梯度方向直方图的实现
2022/03/17 Python