我有以下html代码:

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

所有我想做的是打印到pdf,无论在div中找到一个id为“pdf”。这必须使用JavaScript来完成。"pdf"文件会自动下载,文件名为"foobar.pdf"

我一直在使用jspdf来做到这一点,但它唯一的功能是“文本”,只接受字符串值。我想提交HTML到jspdf,而不是文本。


当前回答

如前所述,您应该使用jsPDF和html2canvas。我还在jsPDF问题中发现了一个函数,它自动将您的pdf分割成多个页面(来源)

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');
    }
  });
}

其他回答

要将div捕获为PDF,您可以使用https://grabz.it解决方案。它有一个简单而灵活的JavaScript API,允许您捕获单个HTML元素(如div或span)的内容

为了实现它,你首先需要获得应用密钥和秘密,并下载(免费的)SDK。

现在来看一个例子。

假设你有HTML:

<div id="features">
    <h4>Acme Camera</h4>
    <label>Price</label>$399<br />
    <label>Rating</label>4.5 out of 5
</div>
<p>Cras ut velit sed purus porttitor aliquam. Nulla tristique magna ac libero tempor, ac vestibulum felisvulput ate. Nam ut velit eget
risus porttitor tristique at ac diam. Sed nisi risus, rutrum a metus suscipit, euismod tristique nulla. Etiam venenatis rutrum risus at
blandit. In hac habitasse platea dictumst. Suspendisse potenti. Phasellus eget vehicula felis.</p>

要捕获特征id下的内容,您需要:

//add the sdk
<script type="text/javascript" src="grabzit.min.js"></script>
<script type="text/javascript">
//login with your key and secret. 
GrabzIt("KEY", "SECRET").ConvertURL("http://www.example.com/my-page.html",
{"target": "#features", "format": "pdf"}).Create();
</script>

请注意目标:#feature。#feature是你的CSS选择器,就像前面的例子一样。现在,当页面加载时,将在脚本标记的相同位置创建图像截图,其中将包含所有的功能div的内容,没有其他内容。

你还可以对div-截图机制进行其他配置和自定义,请在这里查看

jsPDF能够使用插件。为了使它能够打印HTML,你必须包括某些插件,因此必须做以下工作:

登录https://github.com/MrRio/jsPDF下载最新版本。 在你的项目中包含以下脚本: jspdf.js jspdf.plugin.from_html.js jspdf.plugin.split_text_to_size.js jspdf.plugin.standard_fonts_metrics.js

如果希望忽略某些元素,则必须用ID标记它们,然后可以在jsPDF的特殊元素处理程序中忽略该ID。因此你的HTML应该是这样的:

<!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>

然后使用以下JavaScript代码在弹出窗口中打开创建的PDF:

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");

对我来说,这创建了一个漂亮而整洁的PDF,只包括一行“打印此PDF”。

请注意,特殊元素处理程序只处理当前版本中的id,这在GitHub问题中也有说明。州:

因为匹配是针对节点树中的每个元素进行的,所以我希望尽可能快地进行匹配。在这种情况下,它意味着“只匹配元素id”。元素id仍然是jQuery风格的“#id”,但这并不意味着支持所有的jQuery选择器。

因此,将'#ignorePDF'替换为'类选择器'。ignorePDF'没有为我工作。相反,你必须为每个元素添加相同的处理程序,你想忽略这些元素,比如:

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

从示例中还指出,可以选择像'a'或'li'这样的标签。不过,对于大多数用例来说,这可能有点不受限制:

我们支持特殊的元素处理程序。用jquery方式注册它们 ID选择器用于ID或节点名称。(“#iAmID”,“div”,“span”等) 不支持任何其他类型的选择器(class, of 化合物)此时。

要添加的一个非常重要的事情是,您丢失了所有的样式信息(CSS)。幸运的是,jsPDF能够很好地格式化h1、h2、h3等,这对我的目的来说已经足够了。此外,它只打印文本节点中的文本,这意味着它不会打印文本区域等的值。例子:

<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>

一种方法是使用window.print()函数。哪个不需要任何库

Pros

1.不需要外部库。

2.我们也可以只打印选定的身体部位。

3.没有css冲突和js问题。

4.html/js核心功能

简单地添加下面的代码

CSS

@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代码-调用btn点击下函数

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

注意:在每个css对象中使用!important

的例子,

.legend  {
  background: #9DD2E2 !important;
}

2022答:

从HTML元素生成PDF并提示保存文件:

import { jsPDF } from "jsPDF"

function generatePDF() {
  const doc = new jsPDF({ unit: 'pt' }) // create jsPDF object
  const pdfElement = document.getElementById('pdf') // HTML element to be converted to PDF

  doc.html(pdfElement, {
    callback: (pdf) => {
      pdf.save('MyPdfFile.pdf')
    },
    margin: 32, // optional: page margin
    // optional: other HTMLOptions
  })
}
<button onclick="generatePDF()">Save PDF</button>

...

不打印预览PDF文件:

doc.html(pdfElement, {
  callback: (pdf) => {
    const myPdfData = pdf.output('datauristring')
  }
})
<embed type="application/pdf" src={myPdfData} />

... 更多的html: https://github.com/parallax/jsPDF/blob/master/types/index.d.ts

如果您想导出一个表,可以查看Shield UI Grid小部件提供的导出示例。

它是通过像这样扩展配置来实现的:

...
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" }
            ]
        }
    }
}
...