Implementation of html to pdf in pure js

Keywords: Javascript Java Google IE Attribute

There is a perverted requirement in project development, which requires exporting the whole page to pdf format, and keeping all tables, svg pictures and styles on the page.
In short, you want to cut off the whole page like a screenshot and save it as pdf.
Why can't we go to heaven -- -- ___________
After checking, there are still many ways to convert html to pdf. There are probably the following:
1. Most browsers have this function. However, this is not what our customers want. What they want is that they can actively trigger the export of pdf function in the system, so this solution pass es.
2. Use third-party tools. I found a way to use wkhtmltopdf as a tool to export the solution. I tried it in our project, the effect is not good, and the support for svg pictures is not good. pass.
3. Another is to use iText class background to generate java files. But because the page that needs to be exported is a dynamic page, and passing the page directly to the background will lose a lot of styles, so it is still pass.
In the end, there is no good way to do this. We can only go back and ask for the second place. We want to convert html pages into pictures and export pictures to pdf. To support user export and download, and to retain style, it is best to implement pure js front-end.
html to canvas, then use html 2 canvas this js, this online introduction is more, here is no nonsense.
More troublesome is the svg picture, directly using HTML 2 canvas can not convert the content of the svg tag to canvas, and finally after checking a circle of data, locked the js of canvg. Canvg is a plug-in for Google that can convert svg tag content into canvas. As for our project, another difficulty is how to convert glyphicons font icon into canvas, because the support for this font icon is totally different in different browsers. The last way to find out is to replace these font icons with char code and redraw them into canvas. It's no nonsense to generate pictures from canvas. pdf generated by pictures is implemented by jsPDF. After half a day's tossing and turning, I finally got the whole process through, and then I pasted the code step by step.

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

 1 svg2canvas: function(targetElem) {
 2   var svgElem = targetElem.find('svg');
 3   svgElem.each(function(index, node) {
 4     var parentNode = node.parentNode;
 5     //Because of the present IE Direct pairing is not supported svg Label node To retrieve content, you need to cover the current label with a layer div,Through outer layer div Of innerHTML Attribute to get
 6     var tempNode = document.createElement('div');
 7     tempNode.appendChild(node);
 8     var svg = tempNode.innerHTML;
 9     var canvas = document.createElement('canvas');
10     //Transformation
11     canvg(canvas, svg);
12     parentNode.appendChild(canvas);
13   });
14 }

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

 1 glyphicons2canvas: function(targetElem, fontClassName, fontFamilyName) {
 2   var iconElems = targetElem.find('.' + fontClassName);
 3   iconElems.each(function(index, inconNode) {
 4     var fontSize = $(inconNode).css("font-size");
 5     var iconColor = $(inconNode).css("color");
 6     var styleContent = $(inconNode).attr('style');
 7     //Remove"px"
 8     fontSize = fontSize.replace("px", "");
 9     var charCode = getCharCodeByGlyphiconsName(iconName);
10     var myCanvas = document.createElement('canvas');
11     //hold canva The width and height are increased by 2 to show the integrity of the icon.
12     myCanvas.width = parseInt(fontSize) + 2;
13     myCanvas.height = parseInt(fontSize) + 2;
14     myCanvas.style = styleContent;
15     var ctx = myCanvas.getContext('2d');
16     //Setting the color of the drawing content
17     ctx.fillStyle = iconColor;
18     //Set the font size of the drawing and font-family Name
19     ctx.font = fontSize + 'px ' + fontFamilyName;
20     ctx.fillText(String.fromCharCode(charCode), 1, parseInt(fontSize) + 1);
21     $(inconNode).replaceWith(myCanvas);
22   });
23 }
24 //according to glyphicons/glyphicon The class name of the icon is retrieved to the corresponding char code
25 getCharCodeByGlyphiconsName: function(iconName) {
26   switch (iconName) {
27   case("glyphicons-resize-full"):
28     return "0xE216";
29   case ("glyphicons-chevron-left"):
30     return "0xE225";
31   default:
32     return "";
33   }
34 }

Step 3: html to canvas to picture to pdf

 1 html2canvas($("#myExportArea"), {
 2   onrendered: function(canvas) {
 3     var imgData = canvas.toDataURL('image/jpeg');
 4     var img = new Image();
 5     img.src = imgData;
 6     //Depending on the size of the picture pdf Specifications that are executed when the image is loaded successfully*0.225 It's about proportionality.
 7     img.onload = function() {
 8       //Notice here that pdf The horizontal and vertical attributes need to be adjusted according to the ratio of width to height, otherwise there will be incomplete display problems.
 9       if (this.width > this.height) {
10         var doc = new jsPDF('l', 'mm', [this.width * 0.225, this.height * 0.225]);
11       } else {
12         var doc = new jsPDF('p', 'mm', [this.width * 0.225, this.height * 0.225]);
13       }
14       doc.addImage(imgData, 'jpeg', 0, 0, this.width * 0.225, this.height * 0.225);
15       //Save different file names according to download
16       doc.save('report_pdf_' + new Date().getTime() + '.pdf');
17     }
18   },
19   background: "#fff",
20   //Here is the default background for the generated image, otherwise, if you have html If the root node has no background, it will be filled in black.
21   allowTaint: true //Avoid some unrecognized image interference, default is false,Processing stops when confronted with unrecognized image interference html2canvas
22 });

Although the customer's requirements were barely fulfilled in the end, the pdf generated was not as clear as the normal screenshots. For the time being, we can only think of this method at a limited level. If you have a better way, you are welcome to give advice.

Posted by agulaid on Sat, 30 Mar 2019 00:03:27 -0700