使用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实现简单时尚快捷的气泡提示插件
Dec 20 Javascript
javascript动态创建链接的方法
May 13 Javascript
JS基于FileSystemObject创建一个指定路径的TXT文本文件
Aug 05 Javascript
jQueryUI Datepicker组件设置日期高亮
Oct 13 Javascript
快速掌握jQuery插件开发
Jan 19 Javascript
Vue v2.5 调整和更新不完全问题
Oct 24 Javascript
webpack 模块热替换原理
Apr 09 Javascript
vue.js绑定事件监听器示例【基于v-on事件绑定】
Jul 07 Javascript
Vue form表单动态添加组件实战案例
Sep 02 Javascript
JS常用正则表达式超全集(密码强度校验,金额校验,IE版本,IPv4,IPv6校验)
Feb 03 Javascript
vue+django实现下载文件的示例
Mar 24 Vue.js
AJAX实现指定部分页面刷新效果
Oct 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 采集获取指定网址的内容
2010/01/05 PHP
PHP随机数生成代码与使用实例分析
2011/04/08 PHP
PHP中soap用法示例【SoapServer服务端与SoapClient客户端编写】
2018/12/25 PHP
新浪中用来显示flash的函数
2007/04/02 Javascript
javaScript Array(数组)相关方法简述
2009/07/25 Javascript
jQuery 打造动态下滑菜单实现说明
2010/04/15 Javascript
Jsonp 跨域的原理以及Jquery的解决方案
2010/05/18 Javascript
关于UTF-8的客户端用AJAX方式获取GB2312的服务器端乱码问题的解决办法
2010/11/30 Javascript
Colortip基于jquery的信息提示框插件在IE6下面的显示问题修正方法
2010/12/06 Javascript
取消选中单选框radio的三种方式示例介绍
2013/12/23 Javascript
JavaScript用Number方法实现string转int
2014/05/13 Javascript
推荐8款jQuery轻量级树形Tree插件
2014/11/12 Javascript
原生JavaScript+LESS实现瀑布流
2014/12/12 Javascript
JavaScript在Android的WebView中parseInt函数转换不正确问题解决方法
2015/04/25 Javascript
使用js复制链接中的部分文字的方法
2015/07/30 Javascript
js实现文本框支持加减运算的方法
2015/08/19 Javascript
javascript html5实现表单验证
2016/03/01 Javascript
深入理解js generator数据类型
2016/08/16 Javascript
DOM事件探秘篇
2017/02/15 Javascript
javascript 封装Date日期类实例详解
2017/05/28 Javascript
react-router JS 控制路由跳转实例
2017/06/15 Javascript
解决vue.js在编写过程中出现空格不规范报错的问题
2017/09/20 Javascript
vue中如何使用ztree
2018/02/06 Javascript
node删除、复制文件或文件夹示例代码
2019/08/13 Javascript
浅谈vue限制文本框输入数字的正确姿势
2019/09/02 Javascript
taro 实现购物车逻辑的实例代码
2020/06/05 Javascript
Python高效编程技巧
2013/01/07 Python
python多线程扫描端口示例
2014/01/16 Python
python 中的列表生成式、生成器表达式、模块导入
2019/06/19 Python
Python使用xpath实现图片爬取
2020/09/16 Python
经济信息系毕业生自荐信范文
2014/03/15 职场文书
软件售后服务承诺书
2014/05/21 职场文书
中考标语大全
2014/06/05 职场文书
二年级语文上册复习计划
2015/01/19 职场文书
保洁员岗位职责
2015/02/04 职场文书
python基础之停用词过滤详解
2021/04/21 Python