使用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 相关文章推荐
免费空间广告万能消除代码
Sep 04 Javascript
让您的菜单不离网站
Oct 03 Javascript
javascript得到XML某节点的子节点个数的脚本
Oct 11 Javascript
jQuery 浮动广告实现代码
Dec 25 Javascript
各浏览器对click方法的支持差异小结
Jul 31 Javascript
jquery实现控制表格行高亮实例
Jun 05 Javascript
javascript使用正则表达式实现去掉空格之后的字符
Feb 15 Javascript
AngularJS 表达式详解及实例代码
Sep 14 Javascript
Angular2里获取(input file)上传文件的内容的方法
Sep 05 Javascript
Bootstrap实现可折叠分组侧边导航菜单
Mar 07 Javascript
浅谈Ant Design Pro 菜单自定义 icon
Nov 17 Javascript
AJAX引擎原理以及XmlHttpRequest对象的axios、fetch区别详解
Apr 09 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通过串口实现发送短信
2015/07/08 PHP
Javascript下的keyCode键码值表
2007/04/10 Javascript
jQuery 工具函数学习资料
2010/04/29 Javascript
改写一个简单的菜单 弹性大小
2010/12/02 Javascript
Draggable Elements 元素拖拽功能实现代码
2011/03/30 Javascript
使用typeof方法判断undefined类型
2014/09/09 Javascript
JS+CSS实现仿支付宝菜单选中效果代码
2015/09/25 Javascript
jquery拖拽排序简单实现方法(效果增强版)
2016/02/16 Javascript
JavaScript的函数式编程基础指南
2016/03/19 Javascript
jQuery中Ajax全局事件引用方式及各个事件(全局/局部)执行顺序
2016/06/02 Javascript
基于jQuery插件jqzoom实现的图片放大镜效果示例
2017/01/23 Javascript
详解jquery选择器的原理
2017/08/01 jQuery
关于Vue Webpack2单元测试示例详解
2017/08/14 Javascript
浅谈Angular路由复用策略
2017/10/04 Javascript
手写简单的jQuery雪花飘落效果实例
2018/04/22 jQuery
深入浅析Node环境和浏览器的区别
2018/08/14 Javascript
js html实现计算器功能
2018/11/13 Javascript
Vue 嵌套路由使用总结(推荐)
2020/01/13 Javascript
在阿里云服务器上配置CentOS+Nginx+Python+Flask环境
2016/06/18 Python
Python进阶篇之字典操作总结
2016/11/16 Python
Python实现抓取HTML网页并以PDF文件形式保存的方法
2018/05/08 Python
django ajax json的实例代码
2018/05/29 Python
python实现可视化动态CPU性能监控
2018/06/21 Python
Django用户认证系统 Web请求中的认证解析
2019/08/02 Python
python中struct模块之字节型数据的处理方法
2019/08/27 Python
python进程池实现的多进程文件夹copy器完整示例
2019/11/27 Python
python 实现图片上传接口开发 并生成可以访问的图片url
2019/12/18 Python
Python打开文件、文件读写操作、with方式、文件常用函数实例分析
2020/01/07 Python
python匿名函数lambda原理及实例解析
2020/02/07 Python
python应用Axes3D绘图(批量梯度下降算法)
2020/03/25 Python
Python列表如何更新值
2020/05/27 Python
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
AmazeUI中各种的导航式菜单与解决方法
2020/08/19 HTML / CSS
学前教育专业求职信
2014/09/02 职场文书
2019奶茶店创业计划书范本!
2019/07/15 职场文书
SQL Server作业失败:无法确定所有者是否有服务器访问权限的解决方法
2021/06/30 SQL Server