Generate pdf from HTML in div using Javascript

前端 未结 12 993
你的背包
你的背包 2020-11-22 06:10

I have the following html code:



    
        

don\'t print th

相关标签:
12条回答
  • 2020-11-22 06:29

    I was able to get jsPDF to print dynamically created tables from a div.

    $(document).ready(function() {
    
            $("#pdfDiv").click(function() {
    
        var pdf = new jsPDF('p','pt','letter');
        var specialElementHandlers = {
        '#rentalListCan': function (element, renderer) {
            return true;
            }
        };
    
        pdf.addHTML($('#rentalListCan').first(), function() {
            pdf.save("caravan.pdf");
        });
        });
    });
    

    Works great with Chrome and Firefox... formatting is all blown up in IE.

    I also included these:

    <script src="js/jspdf.js"></script>
        <script src="js/jspdf.plugin.from_html.js"></script>
        <script src="js/jspdf.plugin.addhtml.js"></script>
        <script src="//mrrio.github.io/jsPDF/dist/jspdf.debug.js"></script>
        <script src="http://html2canvas.hertzen.com/build/html2canvas.js"></script>
        <script type="text/javascript" src="./libs/FileSaver.js/FileSaver.js"></script>
        <script type="text/javascript" src="./libs/Blob.js/Blob.js"></script>
        <script type="text/javascript" src="./libs/deflate.js"></script>
        <script type="text/javascript" src="./libs/adler32cs.js/adler32cs.js"></script>
    
        <script type="text/javascript" src="js/jspdf.plugin.addimage.js"></script>
        <script type="text/javascript" src="js/jspdf.plugin.sillysvgrenderer.js"></script>
        <script type="text/javascript" src="js/jspdf.plugin.split_text_to_size.js"></script>
        <script type="text/javascript" src="js/jspdf.plugin.standard_fonts_metrics.js"></script>
    
    0 讨论(0)
  • 2020-11-22 06:30

    jsPDF is able to use plugins. In order to enable it to print HTML, you have to include certain plugins and therefore have to do the following:

    1. Go to https://github.com/MrRio/jsPDF and download the latest Version.
    2. Include the following Scripts in your project:
      • jspdf.js
      • jspdf.plugin.from_html.js
      • jspdf.plugin.split_text_to_size.js
      • jspdf.plugin.standard_fonts_metrics.js

    If you want to ignore certain elements, you have to mark them with an ID, which you can then ignore in a special element handler of jsPDF. Therefore your HTML should look like this:

    <!DOCTYPE html>
    <html>
      <body>
        <p id="ignorePDF">don't print this to pdf</p>
        <div>
          <p><font size="3" color="red">print this to pdf</font></p>
        </div>
      </body>
    </html>
    

    Then you use the following JavaScript code to open the created PDF in a PopUp:

    var doc = new jsPDF();          
    var elementHandler = {
      '#ignorePDF': function (element, renderer) {
        return true;
      }
    };
    var source = window.document.getElementsByTagName("body")[0];
    doc.fromHTML(
        source,
        15,
        15,
        {
          'width': 180,'elementHandlers': elementHandler
        });
    
    doc.output("dataurlnewwindow");
    

    For me this created a nice and tidy PDF that only included the line 'print this to pdf'.

    Please note that the special element handlers only deal with IDs in the current version, which is also stated in a GitHub Issue. It states:

    Because the matching is done against every element in the node tree, my desire was to make it as fast as possible. In that case, it meant "Only element IDs are matched" The element IDs are still done in jQuery style "#id", but it does not mean that all jQuery selectors are supported.

    Therefore replacing '#ignorePDF' with class selectors like '.ignorePDF' did not work for me. Instead you will have to add the same handler for each and every element, which you want to ignore like:

    var elementHandler = {
      '#ignoreElement': function (element, renderer) {
        return true;
      },
      '#anotherIdToBeIgnored': function (element, renderer) {
        return true;
      }
    };
    

    From the examples it is also stated that it is possible to select tags like 'a' or 'li'. That might be a little bit to unrestrictive for the most usecases though:

    We support special element handlers. Register them with jQuery-style ID selector for either ID or node name. ("#iAmID", "div", "span" etc.) There is no support for any other type of selectors (class, of compound) at this time.

    One very important thing to add is that you lose all your style information (CSS). Luckily jsPDF is able to nicely format h1, h2, h3 etc., which was enough for my purposes. Additionally it will only print text within text nodes, which means that it will not print the values of textareas and the like. Example:

    <body>
      <ul>
        <!-- This is printed as the element contains a textnode -->        
        <li>Print me!</li>
      </ul>
      <div>
        <!-- This is not printed because jsPDF doesn't deal with the value attribute -->
        <input type="textarea" value="Please print me, too!">
      </div>
    </body>
    
    0 讨论(0)
  • 2020-11-22 06:30

    As mentioned, you should use jsPDF and html2canvas. I've also found a function inside issues of jsPDF which splits automatically your pdf into multiple pages (sources)

    function makePDF() {
    
        var quotes = document.getElementById('container-fluid');
    
        html2canvas(quotes, {
            onrendered: function(canvas) {
    
            //! MAKE YOUR PDF
            var pdf = new jsPDF('p', 'pt', 'letter');
    
            for (var i = 0; i <= quotes.clientHeight/980; i++) {
                //! This is all just html2canvas stuff
                var srcImg  = canvas;
                var sX      = 0;
                var sY      = 980*i; // start 980 pixels down for every new page
                var sWidth  = 900;
                var sHeight = 980;
                var dX      = 0;
                var dY      = 0;
                var dWidth  = 900;
                var dHeight = 980;
    
                window.onePageCanvas = document.createElement("canvas");
                onePageCanvas.setAttribute('width', 900);
                onePageCanvas.setAttribute('height', 980);
                var ctx = onePageCanvas.getContext('2d');
                // details on this usage of this function: 
                // https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images#Slicing
                ctx.drawImage(srcImg,sX,sY,sWidth,sHeight,dX,dY,dWidth,dHeight);
    
                // document.body.appendChild(canvas);
                var canvasDataURL = onePageCanvas.toDataURL("image/png", 1.0);
    
                var width         = onePageCanvas.width;
                var height        = onePageCanvas.clientHeight;
    
                //! If we're on anything other than the first page,
                // add another page
                if (i > 0) {
                    pdf.addPage(612, 791); //8.5" x 11" in pts (in*72)
                }
                //! now we declare that we're working on that page
                pdf.setPage(i+1);
                //! now we add content to that page!
                pdf.addImage(canvasDataURL, 'PNG', 20, 40, (width*.62), (height*.62));
    
            }
            //! after the for loop is finished running, we save the pdf.
            pdf.save('test.pdf');
        }
      });
    }
    
    0 讨论(0)
  • 2020-11-22 06:32

    If you want to export a table, you can take a look at this export sample provided by the Shield UI Grid widget.

    It is done by extending the configuration like this:

    ...
    exportOptions: {
        proxy: "/filesaver/save",
        pdf: {
            fileName: "shieldui-export",
            author: "John Smith",
            dataSource: {
                data: gridData
            },
            readDataSource: true,
            header: {
                cells: [
                    { field: "id", title: "ID", width: 50 },
                    { field: "name", title: "Person Name", width: 100 },
                    { field: "company", title: "Company Name", width: 100 },
                    { field: "email", title: "Email Address" }
                ]
            }
        }
    }
    ...
    
    0 讨论(0)
  • 2020-11-22 06:33
    • No depenencies, pure JS
    • To add CSS or images - do not use relative URLs, use full URLs http://...domain.../path.css or so. It creates separate HTML document and it has no context of main thing.
    • you can also embed images as base64

    This served me for years now:

    export default function printDiv({divId, title}) {
      let mywindow = window.open('', 'PRINT', 'height=650,width=900,top=100,left=150');
    
      mywindow.document.write(`<html><head><title>${title}</title>`);
      mywindow.document.write('</head><body >');
      mywindow.document.write(document.getElementById(divId).innerHTML);
      mywindow.document.write('</body></html>');
    
      mywindow.document.close(); // necessary for IE >= 10
      mywindow.focus(); // necessary for IE >= 10*/
    
      mywindow.print();
      mywindow.close();
    
      return true;
    }
    
    0 讨论(0)
  • 2020-11-22 06:38

    One way is to use window.print() function. Which does not require any library

    Pros

    1.No external library require.

    2.We can print only selected parts of body also.

    3.No css conflicts and js issues.

    4.Core html/js functionality

    ---Simply add below code

    CSS to

    @media print {
            body * {
                visibility: hidden; // part to hide at the time of print
                -webkit-print-color-adjust: exact !important; // not necessary use         
                   if colors not visible
            }
    
            #printBtn {
                visibility: hidden !important; // To hide 
            }
    
            #page-wrapper * {
                visibility: visible; // Print only required part
                text-align: left;
                -webkit-print-color-adjust: exact !important;
            }
        }
    

    JS code - Call bewlow function on btn click

    $scope.printWindow = function () {
      window.print()
    }
    

    Note: Use !important in every css object

    Example -

    .legend  {
      background: #9DD2E2 !important;
    }
    
    0 讨论(0)
提交回复
热议问题