Generate pdf reports using jspdf

  • 2020-07-21 06:42:53
  • OfStack

Since front desk html already generates reports dynamically, and the front desk has one function, an date range component, the report changes dynamically when you drag it without submitting it to the background.
Therefore, js is needed to generate the report:

Components used:


jquery.js
jspdf.js
canvg.js
html2canvas.js
jspdf.plugin.autotable.js

The foreground dynamically generated chart is now generally used canvas or svg of html5. Unfortunately, I met svg. If it was flash, I did not study it.

Since the report still needs to keep the appearance of the original html page, but not the whole html, it is html+svg that really needs to be converted to the pdf report

Premise: jsPDF supports html, but the support is not very good. When you directly generate pdf with 1 html, it only keeps the text, style and structure in html.
table, for example, is missing.
jsPDF does not support svg imports.

Idea: Convert svg to canvas, then convert html+canvas to canvas, then use html2canvas to convert canvas to picture, and finally write the picture to pdf.
Use: if they are table jspdf. plugin. autotable. js

firefox: html2canvas cannot directly convert svg+html to canvas -- > First convert the svg element to canvas -- > html+canvas convert to canvas
chrome:html2canvas can directly convert svg+html to canvas


// All below the node will be specified svg Converted to canvas
// There needs to be :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);
  });
  
}


// Here is the html( The text ) in 1 a iframe Open the inside 
// The main reason is to exclude the interference of other elements and lead to failure 1 Direct output is not successful, only use the shown iframe
// This code is taken from the official website. 
// There is also a problem is: if the page chart Converted to canvas the web The ability to report dynamic changes on the page will be lost. 
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;
  
  // This is where the report is used css Rewrite to iframe According to their own needs 
  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();
  
  /*
  // Here to do 1 Some fine tuning, according to their own needs 
  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;
}


// export pdf
function exportAsPDF(){
  // To get to export pdf the html The root node   
  var chartCenter = document.getElementById("chart-center").outerHTML;
  
  var fbody = openWithIframe(chartCenter);
  svg2canvas(fbody);
  
  //html2canvas The official website's standard approach 
  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");
      */
      
      // Convert the image to: base64 The coding jpg The image. 
      var imgData = canvas.toDataURL('image/jpeg');
      //alert(imgData);
            
      //l: The horizontal,  p Vertical: 
      var doc = new jsPDF('l', 'pt', 'a3');
      //var doc = new jsPDF('p', 'mm', [290, 210]);
      //var doc = new jsPDF();// The default is A4 Since my report is relatively large, I have specially set the size. 
      doc.setFontSize(22);
      doc.setFontType("bolditalic");
      doc.text(500, 30, "Ticket Report"); //x:500, y:30
      
      doc.addImage(imgData, 'jpeg', 10, 60); // Write location: x:10, y:60
      
      doc.addPage();  // new 1 page 
      
      // Here is the sum of table Written to the pdf The inside. 
      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(); // The final will be iframe delete 
    },
    background:"#fff", // Here is the default background for the generated image, otherwise, if your html If the root node does not have a background, it will be filled with black. 
    allowTaint: true  // avoid 1 Some do not recognize the image interference, default as false , it will stop processing when it encounters the interference of non-recognition pictures html2canvas
  });
  
};

This is the end of this article, I hope you enjoy it.


Related articles: