使用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 相关文章推荐
javaScript 关闭浏览器 (不弹出提示框)
Jan 31 Javascript
基于jQuery实现的百度导航li拖放排列效果,即时更新数据库
Jul 31 Javascript
jQuery 计算iframe 窗口大小的方法
May 13 Javascript
Jquery修改页面标题title其它JS失效的解决方法
Oct 31 Javascript
详谈jQuery操纵DOM元素属性 attr()和removeAtrr()方法
Jan 22 Javascript
Markdown+Bootstrap图片自适应属性详解
May 21 Javascript
jQuery密码强度验证控件使用详解
Jan 05 Javascript
JavaScript高阶函数_动力节点Java学院整理
Jun 28 Javascript
JS/HTML5游戏常用算法之碰撞检测 包围盒检测算法详解【凹多边形的分离轴检测算法】
Dec 13 Javascript
利用React Router4实现的服务端直出渲染(SSR)
Jan 07 Javascript
跟混乱的页面弹窗说再见
Apr 11 Javascript
Axios代理配置及封装响应拦截处理方式
Apr 07 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
php删除与复制文件夹及其文件夹下所有文件的实现代码
2013/01/23 PHP
PHP has encountered a Stack overflow问题解决方法
2014/11/03 PHP
PHP浮点数的一个常见问题
2016/03/10 PHP
PHP实现的登录页面信息提示功能示例
2017/07/24 PHP
PHP用PDO如何封装简单易用的DB类详解
2017/07/30 PHP
彻底搞懂PHP 变量结构体
2017/10/11 PHP
PHP读取并输出XML文件数据的简单实现方法
2017/12/22 PHP
html 锁定页面(js遮罩层弹出div效果)
2009/10/27 Javascript
jquery实现智能感知连接外网搜索
2013/05/21 Javascript
简单的邮箱登陆的提示效果类似于yahoo邮箱
2014/02/26 Javascript
JQuery中使用Ajax赋值给全局变量失败异常的解决方法
2014/08/18 Javascript
JS的location.href跳出框架打开新页面的方法
2014/09/04 Javascript
jQuery实现的经典滑动门效果
2015/09/22 Javascript
基于jquery实现页面滚动时顶部导航显示隐藏
2020/04/20 Javascript
浅谈es6中export和export default的作用及区别
2018/02/07 Javascript
小程序点击图片实现自动播放视频
2020/05/29 Javascript
Node.js操作系统OS模块用法分析
2019/01/04 Javascript
vue父组件触发事件改变子组件的值的方法实例详解
2019/05/07 Javascript
javascript实现贪吃蛇小游戏
2020/07/28 Javascript
js 数据类型判断的方法
2020/12/03 Javascript
[05:15]DOTA2英雄梦之声_第16期_灰烬之灵
2014/06/21 DOTA
[00:52]DOTA2第二届亚洲邀请赛预选赛宣传片
2017/01/13 DOTA
Python实现过滤单个Android程序日志脚本分享
2015/01/16 Python
Python各类图像库的图片读写方式总结(推荐)
2018/02/23 Python
PyQt5下拉式复选框QComboCheckBox的实例
2019/06/25 Python
浅谈keras中的keras.utils.to_categorical用法
2020/07/02 Python
python -v 报错问题的解决方法
2020/09/15 Python
CSS3对背景图片的裁剪及尺寸和位置的设定方法
2016/03/07 HTML / CSS
Html5 audio标签样式的修改
2016/01/28 HTML / CSS
档案接收函
2014/01/13 职场文书
酒店销售经理岗位职责
2014/01/31 职场文书
大学奖学金获奖感言
2014/08/15 职场文书
2014个人年度工作总结范文
2014/12/24 职场文书
校园歌手大赛主持词
2015/07/03 职场文书
2015年小学财务工作总结
2015/07/20 职场文书
PostgreSQL并行计算算法及参数强制并行度设置方法
2022/04/06 PostgreSQL