zoukankan      html  css  js  c++  java
  • js生成pdf报表

    由于前台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用hmlt2canvas插件转换成canvas,再将canvas转换成图片,最后将图片写入pdf.
    table的话就使用:jspdf.plugin.autotable.js

    首先将要导入的部分html单独提取出来,写入到一个iframe里面,为了保持外观,还需要将这部分用的css也要写入,再将iframe里面的body标签下面的所有内容转换成canvas. 如果html里面有svg,则先将svg转换成canvas。

    table需要单独导入, jspdf.plugin.autotable.js插件支持json数组,支持table标签的html元素。本文就是用table标签。


    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
        });
        
    };
  • 相关阅读:
    7-10 社交网络图中结点的“重要性”计算(30 point(s)) 【并查集+BFS】
    7-5 打印选课学生名单(25 point(s)) 【排序】
    7-3 堆栈模拟队列(25 point(s)) 【数据结构】
    7-5 家谱处理(30 分) 【数据结构】
    7-7 最强素数(100 分) 【前缀和】
    PAT 天梯赛 L2-022. 重排链表 【数据结构】
    7-1 列出叶结点(25 分) 【数据结构】
    7-6 公路村村通(30 分) 【prime】
    PAT 甲级 1116. Come on! Let's C (20) 【循环判断】
    PAT 甲级 1104. Sum of Number Segments (20) 【数学】
  • 原文地址:https://www.cnblogs.com/overstep/p/4615998.html
Copyright © 2011-2022 走看看