A simple example of pure js to realize html to pdf of recommendation

  • 2021-07-21 07:19:19
  • OfStack

Project development encountered a perverted requirement, need to export 1 entire page to pdf format, and to retain all the tables on the page, svg pictures and styles.

In short, I want to cut off the whole page like screenshot 1 and save it as pdf.

Why don't you go to heaven...

After checking for 1 time, there are still quite a few ways to realize html to pdf, including the following:

1. Most browsers have this function. However, what our customers want is not this. What people want is to export pdf function which can be actively triggered in the system, so this scheme pass.

2. Use third-party tools. I found a use of wkhtmltopdf this tool to export the program, I tried in our project 1, the effect is not good, and the support for svg pictures is not good. pass.

3. There is another one that uses iText class to generate java file in the background. But because the page you need to export is dynamic, and you lose a lot of style by passing the page directly to the background, it is still pass.

In the end, there is no good way, can only settle for the next best, thinking about whether to turn html page into pictures first, and then export pictures to pdf. Because you want to support users to export downloads and preserve styles, it is best to implement a pure js front end.

If html is transferred to canvas, use html2canvas, js. There are many introductions on the Internet, so there is no nonsense here.

What is more troublesome is the picture of svg. It is impossible to convert the content of svg tag into canvas by using html2canvas directly. Finally, after checking the data for one circle, canvg is locked. canvg is a plug-in of Google, which can convert svg tag content into canvas. Specific to our project, there is another difficulty, that is, how to convert the font icon glyphicons into canvas, because the support for this font icon under different browsers is completely different. Finally, we found a way to replace these font icons with char code and redraw them to canvas. Generate pictures by canvas without nonsense. pdf generated from pictures is realized by jsPDF. After tossing for a long time, I finally got through the whole process, and then posted the code step by step.

Step 1: Replace all svg elements in the corresponding dom node with canvas


svg2canvas: function(targetElem) {
 var svgElem = targetElem.find('svg');
 svgElem.each(function(index, node) {
  var parentNode = node.parentNode;
  // Because of the current IE Direct access to svg Label node Fetch the content, so you need to put it outside the current label 1 Layer div Through the outer layer div Adj. innerHTML Property to get the 
  var tempNode = document.createElement('div');
  tempNode.appendChild(node);
  var svg = tempNode.innerHTML;
  var canvas = document.createElement('canvas');
  // Conversion 
  canvg(canvas, svg);
  parentNode.appendChild(canvas);
 });
}

Step 2: Convert the glyphicons font to canvas. If the glyphicons font icon is not used in the project, this step can be ignored


glyphicons2canvas: function(targetElem, fontClassName, fontFamilyName) {
 var iconElems = targetElem.find('.' + fontClassName);
 iconElems.each(function(index, inconNode) {
  var fontSize = $(inconNode).css("font-size");
  var iconColor = $(inconNode).css("color");
  var styleContent = $(inconNode).attr('style');
  // Remove "px"
  fontSize = fontSize.replace("px", "");
  var charCode = getCharCodeByGlyphiconsName(iconName);
  var myCanvas = document.createElement('canvas');
  // Put canva Increase in width and height 2 Is to display the complete icon 
  myCanvas.width = parseInt(fontSize) + 2;
  myCanvas.height = parseInt(fontSize) + 2;
  myCanvas.style = styleContent;
  var ctx = myCanvas.getContext('2d');
  // Set the color of the drawing content 
  ctx.fillStyle = iconColor;
  // Set the font size of the drawing and font-family The name of 
  ctx.font = fontSize + 'px ' + fontFamilyName;
  ctx.fillText(String.fromCharCode(charCode), 1, parseInt(fontSize) + 1);
  $(inconNode).replaceWith(myCanvas);
 });
}
// According to glyphicons/glyphicon The class name of the icon is obtained to the corresponding char code
getCharCodeByGlyphiconsName: function(iconName) {
 switch (iconName) {
 case("glyphicons-resize-full"):
  return "0xE216";
 case ("glyphicons-chevron-left"):
  return "0xE225";
 default:
  return "";
 }
}

Step 3: Turn html to canvas, turn pictures to pdf


html2canvas($("#myExportArea"), {
 onrendered: function(canvas) {
  var imgData = canvas.toDataURL('image/jpeg');
  var img = new Image();
  img.src = imgData;
  // Set according to the size of the picture pdf To be executed when the picture is successfully loaded, the reason why it is necessary to *0.225 It's because of the proportion problem 
  img.onload = function() {
   // Note here that, pdf Horizontal and vertical attributes need to be adjusted according to the ratio of width to height, otherwise the display will be incomplete 
   if (this.width > this.height) {
    var doc = new jsPDF('l', 'mm', [this.width * 0.225, this.height * 0.225]);
   } else {
    var doc = new jsPDF('p', 'mm', [this.width * 0.225, this.height * 0.225]);
   }
   doc.addImage(imgData, 'jpeg', 0, 0, this.width * 0.225, this.height * 0.225);
   // Save to a different file name according to the download 
   doc.save('report_pdf_' + new Date().getTime() + '.pdf');
  }
 },
 background: "#fff",
 // Here, the generated picture is given a default background, otherwise, if your html If the root node has no background, it will be filled with black. 
 allowTaint: true // Avoid 1 Some unrecognized picture interference, the default is false In case of unrecognized image interference, the processing will be stopped html2canvas
});

Although the customer's requirements were barely fulfilled in the end, the generated pdf effect was obviously not as clear as the normal screenshots... Due to the limited level, we can only think of this method for the time being. If you have a better way, please give me some advice.


Related articles: