Project development encountered a perverted need to export a whole page into PDF format, and to keep all the tables on the page, SVG pictures and styles.
In short, just want to cut the entire page down and save it as a PDF.
Why not heaven ...
Checked, the way to achieve HTML to PDF is quite a lot of, probably the following several:
1, most browsers have this function. However, our customers want is not this, people want to be able to actively trigger in the system export to PDF function, so this program pass.
2. Use of third-party tools. I found a way to use wkhtmltopdf this tool to export the scheme, I have tried in our project, the effect is not good, and the SVG image support is not possible. Pass
3. There is also a Java file generated using the Itext class background. But because this page needs to be exported is a dynamic page, and directly to the background of the page will lose a lot of style, so it is pass.
In the end there is no good way, only to retreat and second, think of the HTML page before the first turn into a picture, and then export the picture to PDF. Because to support the user to export the download, and to preserve the style, it is best to be pure JS front-end implementation.
HTML to canvas, the use of Html2canvas this JS, this online introduction is more, here is no nonsense.
More trouble is SVG pictures, directly with Html2canvas can not convert the contents of the SVG tag to canvas, finally checked a circle of data, locked the CANVG this JS. CANVG is a Google plugin that can convert SVG tag content to canvas. Specific to our project, there is also a difficult point, is how to glyphicons this font icon is also converted to canvas, because in different browsers for this font icon support is completely dissimilar. The last method to find is to replace these font icons with char code and redraw them into canvas. Generate pictures from canvas no nonsense. Generated by a picture PDF is implemented with Jspdf. Tossing for the most part of the day, finally the whole process to get through, the next step by post code.
The first step: replace all SVG elements in the corresponding DOM node with the canvas
1Svg2canvas:function(Targetelem) {2 varSvgelem = Targetelem.find (' svg ');3Svgelem.each (function(Index, node) {4 varParentNode =Node.parentnode;5 //because now IE does not support directly to the SVG tag node fetching content, so need to set a layer of div outside the current tag, through the outer Div's innerHTML property to get6 varTempnode = document.createelement (' div ');7 tempnode.appendchild (node);8 varSVG =tempnode.innerhtml;9 varCanvas = document.createelement (' Canvas ');Ten //Conversion One canvg (canvas, SVG); A parentnode.appendchild (canvas); - }); -}
Step two: Turn the glyphicons font into canvas. If the Glyphicons font icon is not used in your project, you can ignore this step
1Glyphicons2canvas:function(Targetelem, Fontclassname, fontfamilyname) {2 varIconelems = Targetelem.find ('. ' +fontclassname);3Iconelems.each (function(index, inconnode) {4 varFontSize = $ (inconnode). CSS ("Font-size");5 varIconcolor = $ (inconnode). CSS ("Color");6 varStylecontent = $ (inconnode). attr (' style '));7 //remove "px"8FontSize = Fontsize.replace ("px", "" ");9 varCharCode =Getcharcodebyglyphiconsname (iconname);Ten varMyCanvas = document.createelement (' Canvas '); One //increase the width of the Canva by 2 to show the complete icon AMycanvas.width = parseint (fontSize) + 2; -Mycanvas.height = parseint (fontSize) + 2; -Mycanvas.style =stylecontent; the varCTX = Mycanvas.getcontext (' 2d '); - //set the color of the drawing content -Ctx.fillstyle =Iconcolor; - //set the font size of the drawing and the name of the font-family +Ctx.font = fontSize + ' px ' +Fontfamilyname; -Ctx.filltext (String.fromCharCode (CharCode), 1, parseint (fontSize) + 1); + $ (inconnode). ReplaceWith (MyCanvas); A }); at } - //gets the corresponding char code according to the class name of the Glyphicons/glyphicon icon -Getcharcodebyglyphiconsname:function(iconname) { - Switch(iconname) { - Case("Glyphicons-resize-full"): - return"0xe216"; in Case("Glyphicons-chevron-left"): - return"0xe225"; to default: + return""; - } the}
Step three: HTML to canvas to picture and then to PDF
1Html2canvas ($ ("#myExportArea"), {2Onrendered:function(canvas) {3 varImgdata = Canvas.todataurl (' image/jpeg '));4 varIMG =NewImage ();5IMG.SRC =Imgdata;6 //according to the size of the picture to set the PDF specifications, to be executed when the picture is loaded successfully, the reason is *0.225 because of the scale problem7Img.onload =function() {8 //It is important to note that the PDF is horizontally and vertically two properties that need to be adjusted according to the ratio of the width to height, or there will be an incomplete display problem.9 if( This. width > This. Height) {Ten varDoc =NewJspdf (' l ', ' mm ', [ This. Width * 0.225, This. Height * 0.225]); One}Else { A varDoc =NewJspdf (' P ', ' mm ', [ This. Width * 0.225, This. Height * 0.225]); - } -Doc.addimage (imgdata, ' jpeg ', 0, 0, This. Width * 0.225, This. Height * 0.225); the //save to a different file name according to the download -Doc.save (' report_pdf_ ' +NewDate (). GetTime () + '. pdf '); - } - }, +Background: "#fff", - //this gives the generated picture the default background, otherwise, if your HTML root node does not set the background, it will be filled with black. +Allowtaint:true //avoid some unrecognized image interference, the default is False, encountered unrecognized image interference will stop processing Html2canvas A});
Although finally reluctantly completed the customer's requirements, but the resulting PDF effect is obviously not as clear as normal ... Level limit, temporarily can only think of this method, if everyone has a better way, welcome guidance.
Pure JS Implementation html to PDF