使用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 last-child 列表最后一项的样式
Jan 22 Javascript
无阻塞加载脚本分析[全]
Jan 20 Javascript
jQuery代码实现发展历程时间轴特效
Jul 30 Javascript
JavaScript实现节点的删除与序号重建实例
Aug 05 Javascript
jQuery获取父元素及父节点的方法小结
Apr 14 Javascript
JS实现类似51job上的地区选择效果示例
Nov 17 Javascript
原生js实现查询天气小应用
Dec 09 Javascript
微信小程序商品详情页规格属性选择示例代码
Oct 30 Javascript
微信小程序封装的HTTP请求示例【附升级版】
May 11 Javascript
Vue实现浏览器打印功能的代码
Apr 17 Javascript
微信小程序picker组件两列关联使用方式
Oct 27 Javascript
JavaScript setTimeout()基本用法有哪些
Nov 04 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
PHP4实际应用经验篇(4)
2006/10/09 PHP
php模拟js函数unescape的函数代码
2012/10/20 PHP
php实现singleton()单例模式实例
2014/11/06 PHP
Zend Studio使用技巧两则
2016/04/01 PHP
php使用ftp实现文件上传与下载功能
2017/07/21 PHP
jquery 插件学习(五)
2012/08/06 Javascript
无限树Jquery插件zTree的常用功能特性总结
2014/09/11 Javascript
原生JS实现美图瀑布流布局赏析
2015/09/07 Javascript
jQuery+CSS3折叠卡片式下拉列表框实现效果
2015/11/02 Javascript
JavaScript通过代码调用Flash显示的方法
2016/02/02 Javascript
Javascript实现通过选择周数显示开始日和结束日的实现代码
2016/05/30 Javascript
使用Script元素发送JSONP请求的方法
2016/06/12 Javascript
详解微信小程序设置底部导航栏目方法
2017/06/29 Javascript
vue动态绑定组件子父组件多表单验证功能的实现代码
2018/05/14 Javascript
解决vue 打包发布去#和页面空白的问题
2018/09/04 Javascript
Vue条件循环判断+计算属性+绑定样式v-bind的实例
2018/09/18 Javascript
vue iview的菜单组件Mune 点击不高亮的解决方案
2019/11/01 Javascript
解决Vue 给mapState中定义的属性赋值报错的问题
2020/06/22 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
2020/07/30 Javascript
Node.js利用Express实现用户注册登陆功能(推荐)
2020/10/26 Javascript
js正则表达式简单校验方法
2021/01/03 Javascript
Python线性方程组求解运算示例
2018/01/17 Python
使用python和pygame绘制繁花曲线的方法
2018/02/24 Python
python将txt等文件中的数据读为numpy数组的方法
2018/12/22 Python
python的sorted用法详解
2019/06/25 Python
python创建与遍历List二维列表的方法
2019/08/16 Python
Python selenium键盘鼠标事件实现过程详解
2020/07/28 Python
HTML5逐步分析实现拖放功能的方法
2020/09/30 HTML / CSS
《纸船和风筝》教学反思
2014/02/15 职场文书
三严三实对照检查材料
2014/08/25 职场文书
水利局群众路线专题民主生活会发言材料
2014/09/21 职场文书
三提三创主题教育活动查摆整改措施
2014/10/25 职场文书
市场营销计划书范文
2015/01/16 职场文书
向雷锋同志学习倡议书
2015/04/27 职场文书
vue基于Teleport实现Modal组件
2021/05/31 Vue.js
Java 在生活中的 10 大应用
2021/11/02 Java/Android