jsPDF 无法使用任何样式

IT技术 javascript css pdf-generation jspdf
2021-02-20 00:28:44

我是使用 jsPDF 的新手,但在我的一生中,我无法将任何 css 应用于这件事!我试过内联、内部和外部都无济于事!我在另一篇 SO 帖子中读到,因为它在技术上将东西打印到文件中,所以我需要一个打印样式表,但这也不起作用。

我有一个非常基本的页面,我只是想让它使用任何 CSS:JS:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="jspdf.js"></script>
<script type="text/javascript" src="./libs/FileSaver.js/FileSaver.js"></script>
<script type="text/javascript" src="./libs/Blob.js/BlobBuilder.js"></script>
<script type="text/javascript" src="jspdf.plugin.standard_fonts_metrics.js"></script> 
<script type="text/javascript" src="jspdf.plugin.split_text_to_size.js"></script>               
<script type="text/javascript" src="jspdf.plugin.from_html.js"></script>
<script>
    $(document).ready(function(){
        $('#dl').click(function(){
        var specialElementHandlers = {
            '#editor': function(element, renderer){
                return true;
            }
        };
        var doc = new jsPDF('landscape');
        doc.fromHTML($('body').get(0), 15, 15, {'width': 170,   'elementHandlers': specialElementHandlers});
        doc.output('save');
        });
    });
</script>

HTML:

<body>
    <div id="dl">Download Maybe?</div>
    <div id="testcase">
        <h1>  
            We support special element handlers. Register them with jQuery-style 
        </h1>
    </div>
</body>

最后是外部样式表:

h1{
    color: red;
}
div{
    color: red;
}

我确信所有内容都被正确包含,并且没有错误,已经检查了所有这些。是否有一些额外的功能我需要调用才能让 css 也能正常工作?请让我知道!非常感谢!您可能有任何其他提示也很感激!

编辑:这是确切的网页:

<html>
    <head>
        <link rel="stylesheet" href="print.css" type="text/css" media="print"/>
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
        <script type="text/javascript" src="jspdf.js"></script>
        <script type="text/javascript" src="./libs/FileSaver.js/FileSaver.js"></script>
        <script type="text/javascript" src="./libs/Blob.js/BlobBuilder.js"></script>
        <script type="text/javascript" src="jspdf.plugin.standard_fonts_metrics.js"></script>
        <script type="text/javascript" src="jspdf.plugin.split_text_to_size.js"></script>               
        <script type="text/javascript" src="jspdf.plugin.from_html.js"></script>
        <script>
            $(document).ready(function(){
                $('#dl').click(function(){
                var specialElementHandlers = {
                    '#editor': function(element, renderer){
                        return true;
                    }
                };
                var doc = new jsPDF('landscape');
                doc.fromHTML($('body').get(0), 15, 15, {'width': 170,   'elementHandlers': specialElementHandlers});
                doc.output('save');
                });
            });
        </script>
    </head>
    <body>
        <div id="dl">Download Maybe?</div>
        <div id="testcase">
            <h1>  
                We support special element handlers. Register them with jQuery-style 
            </h1>
        </div>
    </body>
</html>
4个回答

我认为问题在于你使用media="print"而不是media="screen". 尝试制作两个单独的文件,一个用于打印,一个用于屏幕:

<link rel="stylesheet" href="print.css" type="text/css" media="print"/>
<link rel="stylesheet" href="screen.css" type="text/css" media="screen"/>

屏幕一将包含在浏览器中看到的页面样式。打印页面将包含打印页面时的样式,或者在这种情况下将其保存为 PDF。

编辑

我查看了jsPDF 网站,但我认为它们不支持 CSS。您可以执行以下操作来创建具有不同文本颜色的文档:

doc.setFontSize(22);
doc.setTextColor(255, 0, 0);
doc.text(20, 20, 'This is a title');

doc.setFontSize(16);
doc.setTextColor(0, 255, 0);
doc.text(20, 30, 'This is some normal sized text underneath.');

将此代码放在var doc = new jsPDF('landscape');脚本的正下方

我认为他们不支持 CSS,请查看我更新的答案。
2021-04-16 00:28:44
@Samuraisoulification 不在客户端,但 CasperJS 可以在服务器端截取页面(docs.casperjs.org/en/latest/modules/casper.html#captureselector)上特定元素的屏幕截图
2021-04-16 00:28:44
@Samuraisoulification 您可以使用诸如html2canvas.hertzen.com 之类的东西来截取屏幕截图,然后将其打印出来。
2021-04-19 00:28:44
好吧,如果我不能应用 CSS,JSPDF 对我来说就没用了,你知道有什么库可以让我拍摄 DOM 的一个子集吗?图片还是PDF?如果我可以通过 Id 捕获 dom 的子元素,则格式不是很重要!
2021-05-09 00:28:44
我刚试过这个,虽然它正常设置页面样式,但当我将它保存为 pdf 时,我仍然无法让它设置 pdf 的样式。:(
2021-05-13 00:28:44

你可以试试这个选项,它使用 jsPDF、html2canvas 和 html2pdf 库

从它的自述文件:

包括这个文件:

<script src="jspdf.min.js"></script>
<script src="html2canvas.min.js"></script>
<script src="html2pdf.js"></script>

然后你可以通过运行生成你的pdf:

html2pdf($('body').get(0), {
   margin:       1,
   filename:     'myfile.pdf',
   image:        { type: 'jpeg', quality: 0.98 },
   html2canvas:  { dpi: 192, letterRendering: true },
   jsPDF:        { unit: 'in', format: 'letter', orientation: 'portrait' }
});

您可以使用 jsPDF 捕获屏幕截图,但您还需要 html2canvas。使用 html2canvas 将 html 转换为 canvas 并抓取图像内容。用jsPDF创建一个空的pdf并将html图像内容添加到pdf中并保存:

html2canvas(*html*, {
  onrendered: function(canvas) {
    const contentDataURL = canvas.toDataURL('image/png')
    let pdf = new jsPDF()
    pdf.addImage(contentDataURL, 'JPEG', 20, 20)
    pdf.save('form.pdf')
  }
})

这将保留所有 CSS 但质量会受到一点影响(模糊)。

@samuraiseoul 我们可以使用domtoimage进行复杂的 HTML 渲染

private async generatePDF(elemToPrint: HTMLElement): Promise<void> {
 this.printSection = document.createElement('div');
 this.printSection.id = 'printSection';
 document.body.appendChild(this.printSection);
 const dataUrl = await domtoimage.toPng(elemToPrint, {width: elemToPrint.clientWidth, height: elemToPrint.clientHeight});
 const img = document.createElement('img');
 img.src = dataUrl;
 img.alt = 'The Image';
 this.printSection.appendChild(img);
 setTimeout(() => window.print(), 500); //Just give some time to render stuff while playing with @media print css stuff  
}

这是CSS

@media screen {
 #printSection { 
  display: none;
 }
}
@media print {
  #printSection , #printSection *{
   display: block; // We need the * because only if we display all the items inside the printSection to display as block. then only our mighty firefox will render the second page. :) Hey, that's a bug from FF.
  }
}