使用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 相关文章推荐
JQuery DataTable删除行后的页面更新利用Ajax解决
May 17 Javascript
js实现身份证号码验证的简单实例
Feb 19 Javascript
document.forms[].submit()使用介绍
Feb 19 Javascript
容易造成JavaScript内存泄露几个方面
Sep 04 Javascript
最流行的Node.js精简型和全栈型开发框架介绍
Feb 26 Javascript
JS集成fckeditor及判断内容是否为空的方法
May 27 Javascript
javascript 小数乘法结果错误的处理方法
Jul 28 Javascript
jQuery pagination分页示例详解
Oct 23 jQuery
微信小程序实现swiper切换卡内嵌滚动条不显示的方法示例
Dec 20 Javascript
微信小程序日历效果
Dec 29 Javascript
layui(1.0.9)文件上传upload,前后端的实例代码
Sep 26 Javascript
vue组件中传值EventBus的使用及注意事项说明
Nov 16 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初学者头疼十四条问题大总结
2008/11/12 PHP
探讨各种PHP字符串函数的总结分析
2013/06/05 PHP
解析php中static,const与define的使用区别
2013/06/18 PHP
PHP JS Ip地址及域名格式检测代码
2013/09/27 PHP
PH P5.2至5.5、5.6的新增功能详解
2014/07/14 PHP
yii的CURD操作实例详解
2014/12/04 PHP
php从完整文件路径中分离文件目录和文件名的方法
2015/03/13 PHP
Yii 访问 Gii(脚手架)时出现 403 错误
2018/06/06 PHP
不常用但很实用的PHP预定义变量分析
2019/06/25 PHP
表单元素与非表单元素刷新区别详细解析
2013/11/06 Javascript
javascript判断chrome浏览器的方法
2014/03/26 Javascript
JavaScript中的null和undefined区别介绍
2015/01/01 Javascript
jQuery+jsp实现省市县三级联动效果(附源码)
2015/12/03 Javascript
jquery div模态窗口的简单实例
2016/05/28 Javascript
jQuery利用sort对DOM元素进行排序操作
2016/11/07 Javascript
js窗口震动小程序分享
2016/11/28 Javascript
JavaScript实现经纬度转换成地址功能
2017/03/28 Javascript
JavaScript数据结构之二叉树的查找算法示例
2017/04/13 Javascript
easyui简介_动力节点Java学院整理
2017/07/14 Javascript
hammer.js实现图片手势放大效果
2017/08/29 Javascript
Vue多系统切换实现方案
2018/06/05 Javascript
在微信小程序中使用图表的方法示例
2019/04/25 Javascript
a标签调用js的方法总结
2019/09/05 Javascript
python类参数self使用示例
2014/02/17 Python
python中的字典详细介绍
2014/09/18 Python
Python实现包含min函数的栈
2016/04/29 Python
Python将多个list合并为1个list的方法
2018/06/27 Python
浅谈Python大神都是这样处理XML文件的
2019/05/31 Python
python 带时区的日期格式化操作
2020/10/23 Python
python函数超时自动退出的实操方法
2020/12/28 Python
各大浏览器 CSS3 和 HTML5 兼容速查表 图文
2010/04/01 HTML / CSS
纯css3实现的动画按钮的实例教程
2014/11/17 HTML / CSS
HTML5单页面手势滑屏切换原理
2016/03/21 HTML / CSS
什么是三层交换,说说和路由的区别在那里
2014/09/01 面试题
企业反腐倡廉心得体会
2015/08/15 职场文书
Python内置数据结构列表与元组示例详解
2021/08/04 Python