pdfmake 文档参考

install

这篇文档将概要的讲解pdfmake的基本语法并将展示如何在浏览器中创建PDF文件。如果你对服务器端的打印比较感兴趣请查阅source中的examples文件夹。

在开始的默认配置项中,你应该引入以下两个文件:

 <!doctype html>
 <html lang='en'>
 <head>
 	<meta charset='utf-8'>
 	<title>my first pdfmake example</title>
 	<script src='build/pdfmake.min.js'></script>
 	<script src='build/vfs_fonts.js'></script>
 </head>
 <body>
 (...)

你可以从githup下载以上两个文件或者通过bower安装


    bower install pdfmake

在后者方案中资源文件位于bower_components/pdfmake/build/

文档定义对象(Document definition object)

pdfmake 遵循一个描述性的文档结构

也就是说,你不需要像使用其他类库那样手动的去计算位置或者使用诸如writeText(text,x,y) , movedown的命令,你应该掌握的最基本的概念就是文档定义对象,简单实例如下:


    var docDefinition = { content: 'This is an sample PDF printed with pdfMake' };  

或者比较复杂一些的文档结构(包含多级表格,图片,列表,段落,边距,样式等等)

只要你有了文档定义对象,就可以很容易的创建、打开、打印和下载PDF:


    // open the PDF in a new window
    pdfMake.createPdf(docDefinition).open();

    // print the PDF
    pdfMake.createPdf(docDefinition).print();

    // download the PDF
    pdfMake.createPdf(docDefinition).download('optionalName.pdf');


样式

pdfmake 支持为段落或者内容添加样式


var docDefinition = {
    content: [
        // if you don't need styles, you can use a simple string to define a paragraph
        'This is a standard paragraph, using default style',

        // using a { text: '...' } object lets you set styling properties
        { text: 'This paragraph will have a bigger font', fontSize: 15 },

        // if you set pass an array instead of a string, you'll be able
        // to style any fragment individually
        {
        text: [
            'This paragraph is defined as an array of elements to make it possible to ',
            { text: 'restyle part of it and make it bigger ', fontSize: 15 },
            'than the rest.'
        ]
        }
    ]
};


样式字典

如果你想在文档中重用你的样式,你可以在样式字典中定义通用的样式:


var docDefinition = {
    content: [
        { text: 'This is a header', style: 'header' },
        'No styling here, this is a standard paragraph',
        { text: 'Another text', style: 'anotherStyle' },
        { text: 'Multiple styles applied', style: [ 'header', 'anotherStyle' ] }
    ],

    styles: {
        header: {
        fontSize: 22,
        bold: true
        },
        anotherStyle: {
        italic: true,
        alignment: 'right'
        }
    }
};

为了加深对样式字典的理解,请参阅示例库

默认情况下,段落作为一个栈元依次素垂直排列,当然也可以把一行按照空间划分为列:


var docDefinition = {
  content: [
    'This paragraph fills full width, as there are no columns. Next paragraph however consists of three columns',
    {
      columns: [
        {
          // auto-sized columns have their widths based on their content
          width: 'auto',
          text: 'First column'
        },
        {
          // star-sized columns fill the remaining space
          // if there's more than one star-column, available width is divided equally
          width: '*',
          text: 'Second column'
        },
        {
          // fixed width
          width: 100,
          text: 'Third column'
        },
        {
          // percentage width
          width: '10%',
          text: 'Last column'
        }
      ],
      // optional space between columns
      columnGap: 10
    },
    'This paragraph goes below all columns and has full width'
  ]
};

当然每一类的内容不仅限于纯文本,可以是任意的pdfmake元素,详情参考示例库

表格

概念上的表格非常类似于上文提到的列,他们通常包含表头,边框以及在多行或者多列之间的单元格边距:


var docDefinition = {
  content: [
    {
      table: {
        // headers are automatically repeated if the table spans over multiple pages
        // you can declare how many rows should be treated as headers
        headerRows: 1,
        widths: [ '*', 'auto', 100, '*' ],

        body: [
          [ 'First', 'Second', 'Third', 'The last one' ],
          [ 'Value 1', 'Value 2', 'Value 3', 'Value 4' ],
          [ { text: 'Bold value', bold: true }, 'Val 2', 'Val 3', 'Val 4' ]
        ]
      }
    }
  ]
};

相关的表格详细用法,请参阅见于示例库

列表

pdfmake支持有序和无序列表:


var docDefinition = {
  content: [
    'Bulleted list example:',
    {
      // to treat a paragraph as a bulleted list, set an array of items under the ul key
      ul: [
        'Item 1',
        'Item 2',
        'Item 3',
        { text: 'Item 4', bold: true },
      ]
    },

    'Numbered list example:',
    {
      // for numbered lists set the ol key
      ol: [
        'Item 1',
        'Item 2',
        'Item 3'
      ]
    }
  ]
};


页头和页脚

在pdfmake中页头和页脚可以是静态的也可以是动态的:


var docDefinition = {
  header: 'simple text',

  footer: {
    columns: [
      'Left part',
      { text: 'Right part', alignment: 'right' }
    ]
  },

  content: (...)
};

对于动态创建的文档内容,你可以指定function为页头或者页脚:


var docDefinition = {
  footer: function(currentPage, pageCount) { return currentPage.toString() + ' of ' + pageCount; },
  header: function(currentPage, pageCount) {
    // you can apply any logic and return any valid pdfmake element

    return { text: 'simple text', alignment: (currentPage % 2) ? 'left' : 'right' };
  },
  (...)
};


背景层

背景层会被添加到每一页:


(...)
var docDefinition = {
  background: 'simple text',
  content: (...)
};

背景层页可以包含其他对象(图片,表格等等)或者动态创建:


(...)
var docDefinition = {
  background: function(currentPage) {
    return 'simple text on page ' + currentPage
  },

  content: (...)
};


外边距

任何元素都可以有外边局:


(...)
// margin: [left, top, right, bottom]
//外边距:【左,上,右,下】
{ text: 'sample', margin: [ 5, 2, 10, 20 ] },

// margin: [horizontal, vertical]
//外边距:【水平边距,垂直边距】
{ text: 'another text', margin: [5, 2] },

// margin: equalLeftTopRightBottom
//外边距:【上下左右边距全部相等】
{ text: 'last one', margin: 5 }
(...)


段落栈

通过以上的示例你可能已将发现,当你指定一个内容关键字到一个数组,文档就会变成一个段落栈。在一个嵌入的元素中,你会频繁的使用到这个结构,就像下面这个示例:


var docDefinition = {
  content: [
    'paragraph 1',
    'paragraph 2',
    {
      columns: [
        'first column is a simple text',
        [
          // second column consists of paragraphs
          'paragraph A',
          'paragraph B',
          'these paragraphs will be rendered one below another inside the column'
        ]
      ]
    }
  ]
};

数组的问题就是不无法添加样式属性(假如你想更改字体大小的话),好消息是数组只是pdfmake中栈的一个简写,所以如果你想重新为整个栈重新定义样式,你可以使用扩展的定义规则,如:


var docDefinition = {
  content: [
    'paragraph 1',
    'paragraph 2',
    {
      columns: [
        'first column is a simple text',
        {
          stack: [
            // second column consists of paragraphs
            'paragraph A',
            'paragraph B',
            'these paragraphs will be rendered one below another inside the column'
          ],
          fontSize: 15
        }
      ]
    }
  ]
};


图片

这一部分很简单,只需要使用image节点就可以了{image:’…’}, pdfmake支持JPEG和PNG格式的图片:


var docDefinition = {
  content: [
    {
      // you'll most often use dataURI images on the browser side
      // if no width/height/fit is provided, the original size will be used
      image: 'data:image/jpeg;base64,...encodedContent...'
    },
    {
      // if you specify width, image will scale proportionally
      image: 'data:image/jpeg;base64,...encodedContent...',
      width: 150
    },
    {
      // if you specify both width and height - image will be stretched
      image: 'data:image/jpeg;base64,...encodedContent...',
      width: 150,
      height: 150
    },
    {
      // you can also fit the image inside a rectangle
      image: 'data:image/jpeg;base64,...encodedContent...',
      fit: [100, 100]
    },
    {
      // if you reuse the same image in multiple nodes,
      // you should put it to to images dictionary and reference it by name
      image: 'mySuperImage'
    },
    {
      // under NodeJS (or in case you use virtual file system provided by pdfmake)
      // you can also pass file names here
      image: 'myImageDictionary/image1.jpg'
    }
  ],

  images: {
    mySuperImage: 'data:image/jpeg;base64,...content...'
  }
};

注意无论你是用已经定义好的图片还是直接写死在文档定义结构中,这里的图片源必须是base64格式,笔者就曾经踩过这个坑。直接指定图片链接地址是无效的,当然网上也有很多通过url把图片资源转换成base64的案例,但局限性在于js处理的方式仅仅限定于同源的资源也就是说只要不存在跨域问题就可以。如果都无法满足,建议将图片url发送至后端,借助于java或者其他后端程序处理再返回前端交于javascript使用。 这里顺便把JS如何通过url转换资源为base64格式的代码贴出来以备不时之需。


var img = "imgurl";//imgurl 就是你的图片路径  

function getBase64Image(img) {  
     var canvas = document.createElement("canvas");  
     canvas.width = img.width;  
     canvas.height = img.height;  
     var ctx = canvas.getContext("2d");  
     ctx.drawImage(img, 0, 0, img.width, img.height);  
     var ext = img.src.substring(img.src.lastIndexOf(".")+1).toLowerCase();  
     var dataURL = canvas.toDataURL("image/"+ext);  
     return dataURL;  
}  

var image = new Image();  
image.src = img;  
image.onload = function(){  
  var base64 = getBase64Image(image);  
  console.log(base64);  
}  


分页

你可以根据你的需求在任何一个元素的前或者后指定分页,图片和边个的示例中使用过这个属性:


(...)
	'You can also fit the image inside a rectangle',
	{
		image: 'fonts/sampleImage.jpg',
		fit: [100, 100],
		pageBreak: 'after'
	},
(...)


(...)
	{ text: 'noBorders:', fontSize: 14, bold: true, pageBreak: 'before', margin: [0, 0, 0, 8] },
(...)


页面的大小,方向和外边距


var docDefinition = {
  // a string or { width: number, height: number }
  pageSize: 'A5',

  // by default we use portrait, you can change it to landscape if you wish
  pageOrientation: 'landscape',

  // [left, top, right, bottom] or [horizontal, vertical] or just a number for equal margins
  pageMargins: [ 40, 60, 40, 60 ],
};

相关的pagesize如下:

原文参考地址http://pdfmake.org/#/gettingstarted

  1. 寻寻觅觅 -- Christine Welch
  2. Just the Way You Are -- Bruno Mars
  3. Despacito(Remix) -- Luis Fonsi;Daddy Yankee;Justin Bieber
  4. 没有什么不同 -- 曲婉婷
  5. 故乡--许巍
  6. Jar Of Love -- 曲婉婷
  7. I Really Like You -- Carly Rae Jepsen