我們一起探索前端生成PDF
巧用pdfmake。
在使用層面講如何使用pdfmake生成現有報告,從以下幾方面實現:
- 支持中文
- 預覽頁面搭建
- 封面實現和斷頁
- 頁眉和頁腳實現
- pdfmake顯示類型
- 如何實現內邊距
- table無法居中顯示
支持中文
pdfmake默認不支持中文,需要我們自己實現。找中文的字體文件(ttf結尾的文件)這個任務就交到我們自己手里了,并且字體文件需要支持粗體和斜體,否則字體加粗和斜體屬性不生效。
把我們找到的字體文件,放入pdfmake官方github目錄下examples下,執行
- npm run build:vfs
它會把你放入examples下的所有字體都統一打包到build文件下的vfs_fonts.js中,然后在項目中使用:
- import pdfmake from "pdfmake/build/pdfmake"
- const pdfFonts = require('@/assets/js/vfs_fonts.js')
- pdfMake.vfs = pdfFonts
- pdfMake.fonts = {
- Roboto: {
- normal: 'Roboto-Regular.ttf',
- bold: 'Roboto-Medium.ttf',
- italics: 'Roboto-Italic.ttf',
- bolditalics: 'Roboto-Italic.ttf'
- },
- 微軟雅黑: {
- normal: '微軟雅黑.ttf',
- bold: '微軟雅黑-bold.ttf',
- italics: '微軟雅黑-italics.ttf',
- bolditalics: '微軟雅黑-bolditalics.ttf'
- }
- }
使用時:
- var docDefinition = {
- content: [ '驚天碼盜' ],
- defaultStyle: {
- fontSize: 15,
- bold: true,
- font:"微軟雅黑"
- }
- };
預覽頁面搭建
pdf預覽的邏輯大都是通過iframe實現,通過getDataUrl獲取url地址
- import pdfmake from "pdfmake/build/pdfmake"
- export function previewPdf(params) {
- if(!params) return ;
- const pdfDocGenerator = pdfMake.createPdf(params);
- pdfDocGenerator.getDataUrl( dataUrl=>{
- const targetElement = document.querySelector("#iframeContainer");
- const pdfMakeIframe = document.querySelector("#pdfMakeKey");
- if(pdfMakeIframe){
- pdfMakeIframe.src = dataUrl;
- }else{
- const iframe = document.createElement("iframe");
- iframe.id = 'pdfMakeKey';
- iframe.src = dataUrl;
- targetElement.appendChild(iframe)
- }
- }}
封面實現和斷頁
pdfmake默認是沒有封面這個設置,但是提供了一個設置背景的函數,可以給每個頁面設置一個背景,可以是文字背景,也可以是圖片背景。
- const docDefinition = {
- background: function( currentPage, pageSize){
- if(currentPage === 1){
- return {
- iamge: "bgCoverImgUrl",
- width: pageSize.width,
- height: pageSize.height
- }
- }
- return null;
- }
- content: ["驚天碼盜"]
- }
這個自動斷頁可以說是非常的贊,省去了你復雜的計算。如果你想某一頁單獨放一段文案,或者在某段文案后單獨開一頁,pageBreak可以幫你實現。
- {
- pageOrientation: 'portrait',
- content: [
- {text: 'Text on Portrait'},
- {text: 'Text on Landscape', pageOrientation: 'landscape', pageBreak: 'before'},
- {text: 'Text on Landscape 2', pageOrientation: 'portrait', pageBreak: 'after'},
- {text: 'Text on Portrait 2'},
- ]
- }
頁眉和頁腳
頁眉和頁腳的實現就太方便了。
- const docDefinition = {
- footer: function(currentPage, pageCount) {
- return currentPage.toString() + ' of ' + pageCount;
- },
- header: function(currentPage, pageCount, pageSize) {
- return [{
- columns: [
- {
- text: this.headerContent.left,
- alignment: 'left'
- },
- {
- text: this.headerContent.middle,
- alignment: 'center'
- },
- {
- text: this.headerContent.right,
- alignment: 'right'
- }
- ],
- margin: [10, 20]
- }]
- },
- content: ["驚天碼盜"]
- };
可以精準定位某個頁面做一些特殊的設置。
顯示類型
相對于前端來說大多顯示類型都已經定型了,比如表格、文本、列表、圖片等。在pdfmake中一共給我們提供了這些顯示類型:
text |
普通文本,需要注意的就是字體,如果所提供字體不支持,所設置的屬性就不顯示。同時text可以嵌套。 |
columns |
列,平鋪的列元素。在pdfmake中沒有塊級元素的概念,如果你想平鋪兩個或者多個文本(比如前面icon,后面文本),colums會滿足你。每列之間的距離可以通過columnGap設置。 |
list |
跟html標簽ul或ol相同。 |
table |
表格,唯一提供內邊距屬性的類型。強大到可以實現任何簡單的樣式,相當于display:table。但是弊端也相當明顯,不能垂直居中。 |
image/svg |
圖片。 |
stack | 棧,相當于數組[]。 |
內邊距的實現
text文本在pdfmake中是一個塊級元素(css思路定義)。無法實現內邊距,單個text文本獨占一行。
- const dd = {
- content: [
- 'First paragraph',
- { text:"234", background:'red',color:"#fff",fontSize:20 },
- 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
- ]
- }
在pdfmake類型中只有table可以實現內邊距,那么我們就可以嘗試以table的方式布局,例如
- const dd = {
- content: [
- {
- margin: [0, 20],
- table: {
- body: [
- [
- { text: 'CONTENTS', width: 'auto', fillColor: '#e7e6e6', fontSize: 26 },
- { text: 'Padding ', fillColor: '#58ac5b', color: '#FFF', fontSize: 26 }
- ]
- ]
- },
- layout: {
- defaultBorder: false,
- paddingLeft: function (i, node) {
- if (i === 0) {
- return 10
- }
- return 20
- },
- paddingRight: function (i, node) {
- if (i === 0) {
- return 10
- }
- return 20
- },
- paddingTop: function (i, node) { return 10 },
- paddingBottom: function (i, node) { return 10 }
- }
- }
- ]
- }
效果是:
像目錄這種效果也是table做出來的:
table的缺陷
看似table可以實現任何樣本組合,但是在單元格垂直居中這塊,卡住了。
- {
- // style: 'tableExample',
- table: {
- body: [
- ['Column 1', 'Column 2The following table has nothing more than a body array,The following table has nothing more than a body array,The following table has nothing more than a body array,The following table has nothing more than a body array', 'Column 3'],
- ['One value goes here', 'Another one here', 'OK?']
- ]
- }
- }
其他
目前發現不完美的一點,就是table單元格垂直居中,除了這一點,table很靈活,可以實現多級表頭,嵌套表格,合并單元格,靈活定制各個單元格邊框線條寬度和顏色。
同時還具備水印、加密、二維碼生成、內外鏈接、目錄生成。相比jspdf幫我們節省了很多步驟。那么我們下期聊聊jsPdf。
本文轉載自微信公眾號「驚天碼盜」,可以通過以下二維碼關注。轉載本文請聯系驚天碼盜公眾號。