Angular2 - 使用jspdf从HTML生成pdf

13

我正在做的项目需要能够生成当前用户所在页面的PDF,我将使用jspdf实现。由于我需要生成一个带有HTML的PDF,因此我需要使用addHTML()函数。有很多关于此主题的文章,都说:

你需要使用html2canvasrasterizehtml

我选择使用html2canvas。目前我的代码如下:

import { Injectable, ElementRef, ViewChild } from '@angular/core';
import * as jsPDF from 'jspdf';
import * as d3 from 'd3';
import * as html2canvas from 'html2canvas';

@Injectable ()
export class pdfGeneratorService {

  @ViewChild('to-pdf') element: ElementRef;

  GeneratePDF () {
    html2canvas(this.element.nativeElement, <Html2Canvas.Html2CanvasOptions>{
      onrendered: function(canvas: HTMLCanvasElement) {
        var pdf = new jsPDF('p','pt','a4');

        pdf.addHTML(canvas, function() {
          pdf.save('web.pdf');
        });
      }
    });
  }
}
当调用此函数时,我会收到控制台错误:

EXCEPTION: Error in ./AppComponent class AppComponent - inline template:3:4 caused by: You need either https://github.com/niklasvh/html2canvas or https://github.com/cburgmer/rasterizeHTML.js

为什么会出现这种情况呢?虽然我已经将canvas作为参数传递,但它仍然说我需要使用html2canvas。

你尝试过使用 import * as html2canvas from 'html2canvas/dist/html2canvas.js'; 吗? - Syed Ali Taqi
@SyedAliTaqi,我尝试了你的建议,但是它报错了。 - Vignesh
6个回答

22

我发现有效的方法是添加:

<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.js"></script>

将文件index.html添加到指定位置(它可能位于其他地方)。

然后我使用了:

const elementToPrint = document.getElementById('foo'); //The html element to become a pdf
const pdf = new jsPDF('p', 'pt', 'a4');
pdf.addHTML(elementToPrint, () => {
    doc.save('web.pdf');
});

代码中不再使用html2canvas。
然后您可以删除以下导入:

import * as html2canvas from 'html2canvas';

1
希望导入语句能够正常工作。但现在应该选择这个作为答案。 - Tim Schimandle
@Greg在不导入index.html脚本的情况下,我们能否加载html2canvas.js? - Vignesh
5
除了导入之外,你的代码中在哪里使用了html2canvas?我遇到了错误。你需要使用https://github.com/niklasvh/html2canvas或https://github.com/cburgmer/rasterizeHTML.js。错误:你需要使用https://github.com/niklasvh/html2canvas或https://github.com/cburgmer/rasterizeHTML.js。在Object.e.API.addHTML处。 - Pratap A.K
谢谢,这个解决方案在我的Angular 5项目中起作用了!将脚本添加到index.html中非常重要,如果你只是将它添加到angular.cli.json中,它不会起作用。脚本需要在index.html中。这是目前最新的版本:0.5.0-beta4。 - balazs630
我尝试了你的建议,更新了包到最新版本后它正常工作了。更新的包包括:"html2canvas:1.0.0-alpha.9"、"jspdf": "^1.3.5" 和 "jquery": "^3.3.1"。但是,使用 jspdf 从 HTML 生成 PDF 并没有起作用。 - Vignesh
@Vignesh "npm i html2canvas",并将文件路径("node_modules/html2canvas/dist/html2canvas.js")添加到您的angular.json脚本数组中。 - akcasoy

9

如果有人不想使用cdn脚本,而是想用更多的(angular)方式,那么这对我在Angular 6中有效:

这种方式将为您提供更好的支持和编辑器自动完成,并帮助您避免依赖cdn脚本(如果您像我一样想要避免它们)

基于此优秀答案,由于对我来说很难找到该答案,因此我正在重新分享其中所述的内容,并帮助我在Angular 6中使用jsPDF(所有信用归原始答案的作者)

您应该运行这些命令:

npm install jspdf --save

typings install dt~jspdf --global --save

npm install @types/jspdf --save

请在angular-cli.json中添加以下内容:
"scripts": [ "../node_modules/jspdf/dist/jspdf.min.js" ]

html:

<button (click)="download()">download </button>

组件 ts:

import { Component, OnInit, Inject } from '@angular/core';
import * as jsPDF from 'jspdf'
@Component({
  ...
  providers: [
    { provide: 'Window',  useValue: window }
  ]
})
export class GenratePdfComponent implements OnInit {

  constructor(
    @Inject('Window') private window: Window,
    ) { }

  download() {

        var doc = new jsPDF();
        doc.text(20, 20, 'Hello world!');
        doc.text(20, 30, 'This is client-side Javascript, pumping out a PDF.');
        doc.addPage();
        doc.text(20, 20, 'Do you like that?');

        // Save the PDF
        doc.save('Test.pdf');
    }
}

7

任何仍在尝试将Html div转换为pdf的人都可以选择使用html2pdf,只需几行代码即可轻松完成。

var element = document.getElementById('element-to-print');
html2pdf(element);

你能告诉我这个踩票的原因吗?html2pdf 内部使用 jspdf,这使得事情变得更加容易。有人可能会发现它很有用,因为这个问题是大多数人遇到的。 - Sadiq Ali

2

试试这样:

GeneratePDF () {
    html2canvas(this.element.nativeElement, <Html2Canvas.Html2CanvasOptions>{
      onrendered: function(canvas: HTMLCanvasElement) {
        var pdf = new jsPDF('p','pt','a4');    
        var img = canvas.toDataURL("image/png");
        pdf.addImage(img, 'PNG', 10, 10, 580, 300);
        pdf.save('web.pdf');
      }
    });
  }

1

对于新手来说,提示是要注意你使用的 jspdf 版本:

1.xx:

你需要先安装 html2canvas
   npm install html2canvas

然后将其添加到angular.json文件的脚本部分。
//.angular.json  
 "scripts": [ 
               // make sure you have the correct path 
               "node_modules/html2canvas/dist/html2canvas.min.js"
            ]  

   // let data = this.htmlData.nativeElement; if you use it with @ViewChild('htmlData') 
    htmlData:ElementRef;
    let data = document.body;
    html2canvas(data).then(canvas => {
    // Few necessary setting options
    const imgWidth = 208;
    const pageHeight = 295;
    const imgHeight = canvas.height * imgWidth / canvas.width;
    const heightLeft = imgHeight;

    const contentDataURL = canvas.toDataURL('image/png')
    let pdf = new jspdf('p', 'mm', 'a4'); // A4 size page of PDF
    var position = 0;
    pdf.addImage(contentDataURL, 'PNG', 0, position, imgWidth, imgHeight)
    pdf.save('new-file.pdf'); // Generated PDF
    });

2.xx:

1.xx和2.xx之间有几个重大变化:

移除了以前标记为弃用的API。包括:addHTML、fromHTML、html2pdf、addSvg、addButton、addTextField、addChoiceField、cellInitialize、setFontStyle、setFontType、clip_fixed。

所以以前的代码变成了:

 // let data = this.htmlData.nativeElement; if you use it with @ViewChild('htmlData') 
 htmlData:ElementRef;
 let data = document.body;
    let options : any = {
      orientation: 'p',
      unit: 'px',
      format: 'a0',
      };
    let doc = new jsPDF(options);
     doc.html(data.innerHTML, {
      callback: function (doc) {
            doc.save("angular-demo.pdf");
          },
      margin:15,
      x: 10,
      y: 10
    });
  }

演示

请注意,在2.xx版本中,您无需通过npm安装html2canvas,甚至不需要在angular.json或index.html中包含脚本,因为这是在内部动态完成的。


1
使用方式为 stackblitz example
import {jsPDF} from 'jspdf';

@ViewChild('content', {static: false}) content: ElementRef;


public downloadPDF() {
   const doc = new jsPDF();

   const specialElementHandlers = {
      '#editor': function (element, renderer) {
       return true;
       }
   };

   const content = this.content.nativeElement;

   doc.fromHTML(content.innerHTML, 15, 15, {
      width: 190,
     'elementHandlers': specialElementHandlers
   });

   doc.save('fileName.pdf');
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接