<!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来完成。然后应使用“ foobar.pdf”的文件名自动下载“ pdf”文档。
我一直在使用jspdf来执行此操作,但是它唯一具有的功能是“文本”,仅接受字符串值。我想将HTML提交给jspdf,而不是文本。
#1 楼
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的特殊元素处理程序中忽略。因此,您的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代码来在PopUp中打开创建的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 Issue中也有说明。它指出:
因为对节点树中的每个元素都进行了匹配,所以我希望尽可能快地进行匹配。在这种情况下,这意味着“仅元素ID匹配”。元素ID仍以jQuery样式“ #id”完成,但这并不意味着支持所有jQuery选择器。
因此,用类选择器(例如.ignorePDF)代替'#ignorePDF'对我不起作用。相反,您必须为每个要忽略的元素添加相同的处理程序,例如:
var elementHandler = {
'#ignoreElement': function (element, renderer) {
return true;
},
'#anotherIdToBeIgnored': function (element, renderer) {
return true;
}
};
从示例还可以看出选择“ a”或“ li”之类的标签。不过,对于大多数用例来说,这可能是无限制的:
我们支持特殊的元素处理程序。使用jQuery-style
ID选择器注册ID或节点名称。 (“ #iAmID”,“ div”,“ span”等)
目前不支持任何其他类型的选择器(
复合的类)。
要添加的一个非常重要的事情是您丢失了所有样式信息(CSS)。幸运的是,jsPDF能够很好地格式化h1,h2,h3等格式,这足以满足我的目的。另外,它将仅打印文本节点内的文本,这意味着它将不打印textareas等的值。示例:
<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>
评论
我猜元素处理程序可以是一个类吗?从语义上讲,这将更符合HTML5标准。 ID不仅在CSS中具有过多的特殊性,而且还必须是唯一的。
–紧急
2015年1月3日,7:28
不,据我所知,类目前不是有效的选择器,如它们的示例所述:“我们支持特殊的元素处理程序。请使用jQuery样式的ID选择器为ID或节点名称注册它们。(“#iAmID”, “”(“ div”,“ span”等)。目前不支持任何其他类型的选择器(类,复合类)。不过,如果标签名称与您的用例相符并且没有在页面上隐藏其他重要元素,则仍可以使用标签名称。
–snrlx
2015年1月6日在9:02
他们在其页面parall.ax/products/jspdf上声明通过垫片支持IE6 +。我自己还没有尝试过。
–snrlx
15年3月6日在10:41
@snrlx我得到空白的pdf并出现此错误:renderer.pdf.sHashCode不是函数
–莉萨·所罗门(Lisa Solomon)
16 Mar 23 '16 at 3:39
“如果要忽略某些元素,则必须用ID标记它们”-一个很棒的库,被倒置的需求毁坏了。 OP希望打印单个
,它可能是数百个之一-因此他必须标记所有不需要的DOM元素?
–莫格说要恢复莫妮卡
17年1月24日,19:13
–莫格说要恢复莫妮卡
17年1月24日,19:13
#2 楼
这是简单的解决方案。这对我有用。您可以使用javascript打印概念并将其简单保存为pdf。<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript">
$("#btnPrint").live("click", function () {
var divContents = $("#dvContainer").html();
var printWindow = window.open('', '', 'height=400,width=800');
printWindow.document.write('<html><head><title>DIV Contents</title>');
printWindow.document.write('</head><body >');
printWindow.document.write(divContents);
printWindow.document.write('</body></html>');
printWindow.document.close();
printWindow.print();
});
</script>
</head>
<body>
<form id="form1">
<div id="dvContainer">
This content needs to be printed.
</div>
<input type="button" value="Print Div Contents" id="btnPrint" />
</form>
</body>
</html>
评论
“并且简单地将其另存为pdf”-我错过了这一部分。你怎么做呢?
–莫格说要恢复莫妮卡
17年1月24日在19:16
这对我有用,为了解决CSS样式问题,我创建了另一个名为printPDF.css的css文件,并使用链接标记添加了上述示例中的代码:printWindow.document.write('
–Prime_Coder
17年2月16日在6:43
一些评论:1)您不需要特定的样式表即可进行打印。在您当前的样式表中,执行以下操作:@media print {.pageBreak {page-break-before:always; } .labelPdf {font-weight:bold; font-size:20px; } .noPrintPdf {display:none;并根据需要使用这些类。 2).live(“ click”,...)对我不起作用,因此我改用.on(“ click”,...)。
– Davidson Lima
17年9月13日14:19
@DavidsonLima此代码创建一个新窗口,该窗口将看不到旧窗口的CSS。这就是为什么它“忽略” css,而不忽略,只是在新窗口中没有加载。只需将其加载到头部,它将被渲染。
–卢卡斯·里西斯(Lukas Liesis)
18年5月6日在13:40
万一有人尝试使用Angular做到这一点,请将CSS文件放在资产文件夹中。
– rgantla
19年3月14日在16:34
#3 楼
您可以使用autoPrint()并将输出设置为'dataurlnewwindow',如下所示:function printPDF() {
var printDoc = new jsPDF();
printDoc.fromHTML($('#pdf').get(0), 10, 10, {'width': 180});
printDoc.autoPrint();
printDoc.output("dataurlnewwindow"); // this opens a new popup, after this the PDF opens the print window view but there are browser inconsistencies with how this is handled
}
评论
我很好奇,这对OP以外的其他人有作用吗?通过阅读代码,我似乎了解到它仅适用于具有ID的元素。无论如何,我可能不知道如何完成这项工作,这可能比这还要复杂。
–迈克尔
2014年4月25日在15:31
从我观察到的,非常讽刺的是,fromHTML仅在作为参数发送的元素不包含任何HTML时才起作用:仅支持纯文本。 Kinda杀死了imo整个事情的目的。
–迈克尔
2014-4-25 15:40
为我完美地工作。您不需要传入的元素具有ID。这就是复制者找到他想要传递的节点的方式。此外,该解决方案也可以在没有“ printDoc.autoPrint()”的情况下使用。如果要在代码中保留此特定行,则需要包括autoPrint-Plugin。
–snrlx
14年7月18日在11:52
#4 楼
如果您需要下载特定页面的pdf文件,只需添加这样的按钮<h4 onclick="window.print();"> Print </h4>
使用window.print()打印所有页面,而不仅仅是div
评论
如果要创建iframe的可下载pdf文件,请添加一个简单的补充,然后使用开发人员控制台:document.querySelector(“#myIframe”)。contentWindow.print()
– ioCron
19-3-14在12:32
#5 楼
如前所述,您应该使用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');
}
});
}
评论
它不会转换图像
– Probosckie
17 Mar 4 '17 at 9:11
感谢您的回答,您能否提供有关如何将其转换为A4页面格式的任何提示?
–约翰内斯·马特沃索扬(Johannes Matevosyan)
18年5月14日上午10:16
这实际上并不是一个好的矢量pdf,它使用画布制作了很多位图,并将它们堆叠为图像。结果有很多缺点-大,低质量,无法从PDF复制和粘贴等。
–罗马Zenka
19年1月4日在19:10
jsfiddle.net/jfr34mgL我写了这个例子来覆盖多页图像
– Ryan Loggerythm
9月21日21:15
#6 楼
没有依赖关系,纯JS
要添加CSS或图像-不要使用相对URL,请使用完整URL
http://...domain.../path.css
左右。它创建了单独的HTML文档,没有主要内容。您还可以将图像作为base64嵌入
这为我服务了很多年:
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;
}
评论
这样做的问题是pdf中不会包含任何CSS效果。
–Shadab Faiz
18年5月7日在9:38
@ShadabFaiz它将但可能与主窗口不同。您仍然可以在此html中添加自定义CSS。
–卢卡斯·里西斯(Lukas Liesis)
18年5月7日在19:26
是的同意您可以在窗口中添加CSS,但是如何在pdf文件中打印结果?
– Mirko Cianfarani
18年5月29日在16:25
但是不渲染图像。
–简Pi
18-09-26在10:56
我喜欢这个!在这里和那里进行一些调整,看起来不错。还有一件小事不要去除处的多余间距,它需要这个:P
– phrogg
2月18日上午10:17
#7 楼
一种方法是使用window.print()函数。不需要任何库专业版
1.不需要外部库。
2.我们也只能打印选定的身体部位。
3.没有css冲突和js问题。
4.Core 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 click上调用bewlow函数
$scope.printWindow = function () {
window.print()
}
注意:在每个CSS对象中使用!important
示例-
.legend {
background: #9DD2E2 !important;
}
评论
浏览器的打印功能存在问题。用户通常为“打印”视图选择默认选项(页边距,页面大小等)。因此,在没有培训用户的情况下很难生成具有所需样式的所需PDF,这更加困难并且几乎不可能...
–拉赫玛特·阿里(Rahmat Ali)
19-09-27在10:59
#8 楼
我使用jspdf和html2canvas进行css渲染,并导出特定div的内容,因为这是我的代码$(document).ready(function () {
let btn=$('#c-oreder-preview');
btn.text('download');
btn.on('click',()=> {
$('#c-invoice').modal('show');
setTimeout(function () {
html2canvas(document.querySelector("#c-print")).then(canvas => {
//$("#previewBeforeDownload").html(canvas);
var imgData = canvas.toDataURL("image/jpeg",1);
var pdf = new jsPDF("p", "mm", "a4");
var pageWidth = pdf.internal.pageSize.getWidth();
var pageHeight = pdf.internal.pageSize.getHeight();
var imageWidth = canvas.width;
var imageHeight = canvas.height;
var ratio = imageWidth/imageHeight >= pageWidth/pageHeight ? pageWidth/imageWidth : pageHeight/imageHeight;
//pdf = new jsPDF(this.state.orientation, undefined, format);
pdf.addImage(imgData, 'JPEG', 0, 0, imageWidth * ratio, imageHeight * ratio);
pdf.save("invoice.pdf");
//$("#previewBeforeDownload").hide();
$('#c-invoice').modal('hide');
});
},500);
});
});
评论
这项工作,但它将内容转换为图像
– Samad
19年8月17日在8:13
另外,如何设置分页符,以便如果内容/图像不适合当前页面,则将其打印在新页面上?
–SHEKHAR SHETE
3月5日5:53
#9 楼
使用pdfMake.js和此要点。(我在这里找到了Gist以及指向html-to-pdfmake软件包的链接,但最终我暂时不使用它。)
在
npm install pdfmake
之后保存了htmlToPdf.js
中的要点我是这样使用的: const pdfMakeX = require('pdfmake/build/pdfmake.js');
const pdfFontsX = require('pdfmake-unicode/dist/pdfmake-unicode.js');
pdfMakeX.vfs = pdfFontsX.pdfMake.vfs;
import * as pdfMake from 'pdfmake/build/pdfmake';
import htmlToPdf from './htmlToPdf.js';
var docDef = htmlToPdf(`<b>Sample</b>`);
pdfMake.createPdf({content:docDef}).download('sample.pdf');
备注:
我的用例是从markdown文档(带有markdown-it)创建相关的html,然后生成pdf,然后上传其二进制内容(可以通过
pdfMake
的getBuffer()
函数获得),全部来自浏览器。生成的pdf证明比使用我尝试过的其他解决方案的这种html更好。我对我接受的答案中从
jsPDF.fromHTML()
得到的结果不满意,因为该解决方案很容易与特殊字符混淆在我的HTML中显然被解释为一种标记,并且完全弄乱了生成的PDF。使用基于画布的解决方案(例如已弃用的
jsPDF.from_html()
函数,不要与接受的答案相混淆)不是对我来说是一个选项,因为我希望生成的PDF中的文本是可粘贴的,而基于画布的解决方案则生成基于位图的PDF。直接降价到md到pdf之类的pdf转换器仅在服务器端使用,不适用于我。
对我来说,使用浏览器的打印功能将不起作用,因为我不想显示生成的PDF,而是上传其二进制内容。
评论
如果我正确阅读了代码,这不支持CSS边框样式(例如在表格上),对吗?
– ninjagecko
19-10-26在4:16
不在主题上,我使用pdfmake来创建内容不是来自html的pdf。我的问题是:当使用其方法pdfMake.createPdf(docDefinition).open()时,如何提供自己的特定文件名而不是随机文件名?
– Lex Soft
7月22日15:31
现在成为主题,您提到的要点不存在。您说最终没有使用html-to-pdfmake的问题是什么?我在github中看到它最近仍在维护。
– Lex Soft
7月22日15:50
#10 楼
如果要导出表,可以查看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" }
]
}
}
}
...
评论
“导出为PDF”功能导致PDF文档为空。
–理查德·纳莱辛斯基(Richard Nalezynski)
16-11-10在2:46
您的终端上的配置可能有误...如果需要,请发布带有shieldui标签的问题
–弗拉基米尔·乔治(Vladimir Georgiev)
17年8月21日在9:59
#11 楼
我能够获得jsPDF来从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");
});
});
});
与Chrome和Firefox兼容...在IE中格式化全部失败。
我还包括这些:
<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>
评论
您能发表例子吗,您如何通过html
– Erum
15年4月15日在11:50
但是您的代码是
评论
如上所述,我不想使用“文本”功能。我想给它HTML。您的链接仅处理纯文本,而不处理htmljsPDF确实具有fromHTML函数;请参见以下网址的“ HTML Renderer”示例:mrrio.github.io/jsPDF
在此处尝试jsPDF教程freakyjolly.com/create-multipage-html-pdf-jspdf-html2canvas