使用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 相关文章推荐
node中socket.io的事件使用详解
Dec 15 Javascript
深入探讨JavaScript String对象
Mar 09 Javascript
JS根据生日算年龄的方法
May 05 Javascript
js实现显示当前状态的导航效果代码
Aug 28 Javascript
Js的Array数组对象详解
Feb 22 Javascript
JavaScript中的Reflect对象详解(ES6新特性)
Jul 22 Javascript
bootstrap动态添加面包屑(breadcrumb)及其响应事件的方法
May 25 Javascript
JavaScript创建防篡改对象的方法分析
Dec 30 Javascript
如何写好一个vue组件,老夫的一年经验全在这了(推荐)
May 18 Javascript
vue自定义指令和动态路由实现权限控制
Aug 28 Javascript
JavaScript 实现拖拽效果组件功能(兼容移动端)
Nov 11 Javascript
javascript中layim之查找好友查找群组
Feb 06 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使浏览器直接下载pdf文件的方法
2013/11/15 PHP
php实现批量下载百度云盘文件例子分享
2014/04/10 PHP
PHP正则表达式函数preg_replace用法实例分析
2020/06/04 PHP
层序遍历在ExtJs的TreePanel中的应用
2009/10/16 Javascript
密码强度检测效果实现原理与代码
2013/01/04 Javascript
javascript定时变换图片实例代码
2013/03/17 Javascript
JS操作Cookie写入和读取实例代码
2013/10/20 Javascript
js控制iframe的高度/宽度让其自适应内容
2014/04/09 Javascript
JavaScript中的toDateString()方法使用详解
2015/06/12 Javascript
JavaScript动态添加css样式和script标签
2016/07/19 Javascript
JavaScript鼠标事件,点击鼠标右键,弹出div的简单实例
2016/08/03 Javascript
通过BootStrap-select插件 js jQuery控制select属性变化
2017/01/03 Javascript
Angular使用$http.jsonp发送跨站请求的方法
2017/03/16 Javascript
BootStrap Fileinput插件和Bootstrap table表格插件相结合实现文件上传、预览、提交的导入Excel数据操作步骤
2017/08/07 Javascript
Laravel 如何在blade文件中使用Vue组件的示例代码
2020/06/28 Javascript
[01:00:06]加油DOTA_EP01_网络版
2014/08/09 DOTA
python中的函数用法入门教程
2014/09/02 Python
Python中的默认参数实例分析
2018/01/29 Python
Python开发的十个小贴士和技巧及长常犯错误
2018/09/27 Python
在PyCharm导航区中打开多个Project的关闭方法
2019/01/17 Python
django 基于中间件实现限制ip频繁访问过程详解
2019/07/30 Python
python实现邮件自动发送
2019/08/10 Python
numpy np.newaxis 的实用分享
2019/11/30 Python
Python web框架(django,flask)实现mysql数据库读写分离的示例
2020/11/18 Python
python 利用jieba.analyse进行 关键词提取
2020/12/17 Python
纯CSS3实现带动画效果导航菜单无需js
2013/09/27 HTML / CSS
德国珠宝和配件商店:Styleserver
2021/02/23 全球购物
计算机专业毕业生自荐信
2013/12/31 职场文书
纪念9.18事变演讲稿
2014/09/14 职场文书
法定代表人授权委托书格式
2014/10/14 职场文书
群众路线专项整治方案
2014/10/27 职场文书
暂停营业通知
2015/04/25 职场文书
美容院员工规章制度
2015/08/05 职场文书
任命书格式模板
2015/09/22 职场文书
浅析MongoDB之安全认证
2021/06/26 MongoDB
Python matplotlib绘制雷达图
2022/04/13 Python