使用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 使用简明教程
Mar 05 Javascript
js实现固定显示区域内自动缩放图片的方法
Jul 18 Javascript
js实现prototype扩展的方法(字符串,日期,数组扩展)
Jan 14 Javascript
AngularJS入门教程之Scope(作用域)
Jul 27 Javascript
需要牢记的JavaScript基础知识
Sep 25 Javascript
vue2 中二级路由高亮问题及配置方法
Jun 10 Javascript
extjs图表绘制之条形图实现方法分析
Mar 06 Javascript
JS组件库AlloyTouch实现图片轮播过程解析
May 29 Javascript
原生js实现拖拽移动与缩放效果
Aug 24 Javascript
让Vue响应Map或Set的变化操作
Nov 11 Javascript
antd table按表格里的日期去排序操作
Nov 17 Javascript
Vue包大小优化的实现(从1.72M到94K)
Feb 18 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
中国站长站 For Dede4.0 采集规则
2007/05/27 PHP
php socket方式提交的post详解
2008/07/19 PHP
php中使用preg_replace函数匹配图片并加上链接的方法
2013/02/06 PHP
完美解决thinkphp验证码出错无法显示的方法
2014/12/09 PHP
表单提交错误后返回内容消失问题的解决方法(PHP网站)
2015/10/20 PHP
详解js异步文件加载器
2016/01/24 PHP
PHP全局变量与超级全局变量区别分析
2016/04/01 PHP
CI框架源码解读之URI.php中_fetch_uri_string()函数用法分析
2016/05/18 PHP
浅析onsubmit校验表单时利用ajax的return false无效问题
2013/07/10 Javascript
js+cookies实现悬浮购物车的方法
2015/05/25 Javascript
js实现继承的5种方式
2015/12/01 Javascript
JSON+Jquery省市区三级联动
2016/01/13 Javascript
AngularJS实现ajax请求的方法
2016/11/22 Javascript
jQuery实现网页拼图游戏
2020/04/22 jQuery
vue.js购物车添加商品组件的方法
2019/09/17 Javascript
浅谈layui分页控件field参数接收对象的问题
2019/09/20 Javascript
[27:28]Ti4 冒泡赛第二天 iG vs NEWBEE 1
2014/07/15 DOTA
[01:11:08]Winstrike vs NB 2018国际邀请赛淘汰赛BO1 8.21
2018/08/22 DOTA
Python实现感知器模型、两层神经网络
2017/12/19 Python
教你使用python画一朵花送女朋友
2018/03/29 Python
Python返回数组/List长度的实例
2018/06/23 Python
PyCharm设置SSH远程调试的方法
2018/07/17 Python
Python WSGI的深入理解
2018/08/01 Python
python 实现UTC时间加减的方法
2018/12/31 Python
vscode 配置 python3开发环境的方法
2019/09/19 Python
使用pyplot.matshow()函数添加绘图标题
2020/06/16 Python
python中format函数如何使用
2020/06/22 Python
python 实现图片批量压缩的示例
2020/12/18 Python
英国办公用品商店:Office Outlet
2018/04/04 全球购物
Marlies Dekkers内衣荷兰官方网店:荷兰奢侈内衣品牌
2020/03/27 全球购物
大学校园生活自我鉴定
2014/01/13 职场文书
企业承诺书格式范文
2015/04/28 职场文书
深入理解python协程
2021/06/15 Python
Python实现列表拼接和去重的三种方式
2021/07/02 Python
div与span之间的区别与使用介绍
2021/12/06 HTML / CSS
使用python生成大量数据写入es数据库并查询操作(2)
2022/09/23 Python