使用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 相关文章推荐
jqPlot jquery的页面图表绘制工具
Jul 25 Javascript
轻轻松松学JS调试(不下载任何工具)
Apr 14 Javascript
jquery cookie的用法总结
Nov 18 Javascript
使用Chrome调试JavaScript的断点设置和调试技巧
Dec 16 Javascript
JavaScript中Function()函数的使用教程
Jun 04 Javascript
遮罩层点击按钮弹出并且具有拖动和关闭效果(两种方法)
Aug 20 Javascript
JSON遍历方式实例总结
Dec 07 Javascript
AngularJS中如何使用$parse或$eval在运行时对Scope变量赋值
Jan 25 Javascript
微信小程序 实例开发总结
Apr 26 Javascript
浅谈React组件之性能优化
Mar 02 Javascript
vue如何将v-for中的表格导出来
May 07 Javascript
基于layPage插件实现两种分页方式浅析
Jul 27 Javascript
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学习之PHP运算符
2006/10/09 PHP
用PHP控制用户的浏览器--ob*函数的使用说明
2007/03/16 PHP
简单介绍下 PHP5 中引入的 MYSQLI的用途
2007/03/19 PHP
五个PHP程序员工具
2008/05/26 PHP
php的webservice的wsdl的XML无法显示问题的解决方法
2014/03/11 PHP
PHP中的switch语句的用法实例详解
2015/10/21 PHP
PHP中str_split()函数的用法讲解
2019/04/11 PHP
小程序微信支付功能配置方法示例详解【基于thinkPHP】
2019/05/05 PHP
PHP实现笛卡尔积算法的实例讲解
2019/12/22 PHP
PHP中关于php.ini参数优化详解
2020/02/28 PHP
接收键盘指令的脚本
2006/06/26 Javascript
JQuery this 和 $(this) 的区别
2009/08/23 Javascript
javascript模拟实现C# String.format函数功能代码
2013/11/25 Javascript
js几秒以后倒计时跳转示例
2013/12/26 Javascript
node.js中的fs.fchmod方法使用说明
2014/12/16 Javascript
jQuery前端分页示例分享
2015/02/10 Javascript
基于javascript代码检测访问网页的浏览器呈现引擎、平台、Windows操作系统、移动设备和游戏系统
2015/12/03 Javascript
获取input标签的所有属性的方法
2016/06/28 Javascript
关于JS Lodop打印插件打印Bootstrap样式错乱问题的解决方案
2016/12/23 Javascript
关于vue的语法规则检测报错问题的解决
2018/05/21 Javascript
angularJs中json数据转换与本地存储的实例
2018/10/08 Javascript
Python使用MyQR制作专属动态彩色二维码功能
2019/06/04 Python
python使用Matplotlib改变坐标轴的默认位置
2019/10/18 Python
Python requests模块cookie实例解析
2020/04/14 Python
tensorflow 2.1.0 安装与实战教程(CASIA FACE v5)
2020/06/30 Python
Docker如何部署Python项目的实现详解
2020/10/26 Python
金融专业个人求职信
2013/09/22 职场文书
班主任工作经验材料
2014/02/02 职场文书
优秀高中生事迹材料
2014/02/11 职场文书
2014年政务公开工作总结
2014/12/09 职场文书
2015年环卫工作总结
2015/04/28 职场文书
西柏坡观后感
2015/06/08 职场文书
工作表现证明
2015/06/15 职场文书
优秀党员主要事迹范文
2015/11/05 职场文书
redis连接被拒绝的解决方案
2021/04/12 Redis
教你使用TensorFlow2识别验证码
2021/06/11 Python