下面小编就为大家带来一篇 JS 导出 PDF 插件的方法 (支持中文、图片使用路径)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
Javascript 是一种由 Netscape 的 LiveScript 发展而来的原型化继承的基于对象的动态类型的区分大小写的客户端脚本语言,主要目的是为了解决服务器端语言,比如 Perl,遗留的速度问题,为客户提供更流畅的浏览效果。
在 web 上想做一个导出 PDF 的功能,发现 jsPDF 比较多人推荐,遗憾的是不支持中文,最后找到 pdfmake,很好地解决了此问题。它的效果可以先到 http://pdfmake.org/playground.html 查看。在使用过程中,还发现图片的插入是相对繁琐的一件事。
针对这些问题,本文的主要内容可分为三部分:
•pdfmake 的基本使用方法;
• 如何解决中文问题;
• 如何通过指定图片地址插入图片。
pdfmake 的基本使用方法
1. 包含以下两个文件
- <script src="build/pdfmake.min.js">
- </script>
- <script src="build/vfs_fonts.js">
- </script>
2. 在 JS 代码中声明一个 Document-definition 对象,这个是 pdfmake 自己的术语。简单点说,就是创建一个至少包含 content 属性的对象。然后就可以调用 pdfMake 的方法导出 PDF,具体见如下代码:
- <script type="text/javascript">
- //创建Document-definition对象
- var dd = {
- content: [
- 'One paragraph',
- 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
- ]
- };
- //导出PDF
- pdfMake.createPdf(dd).download();
- </script>
按照上例操作,就可以看到提示文件下载了。关于 pdfmake 的完整教程请登陆 pdfmake 项目查看。
pdfmake 支持中文
三个步骤:
1. 到 pdfmake 项目网站,把工程都下载下来,然后进入工程目录将字体文件(比如微软雅黑. ttf) 放到 examples/fonts 目录下,然后使用 grunt dump_dir 生成新的 vfs_fonts.js 文件;
从上面描述可知该工程是通过 grunt 管理的,如果无相关知识,请上网先补习下。
grunt dump_dir 命令会将 fonts 目录下所有文件都打包,因此无用文件请别放进去。
微软雅黑. ttf 网上一搜一大把,WINDOWS 电脑系统盘下存放字体的目录也找得到。
2. 回到自己的例子代码中,JS 代码中修改 pdfMake 的 fonts 对象,声明当前要用到字体:
- pdfMake.fonts = {
- Roboto: {
- normal: 'Roboto-Regular.ttf',
- bold: 'Roboto-Medium.ttf',
- italics: 'Roboto-Italic.ttf',
- bolditalics: 'Roboto-Italic.ttf'
- },
- 微软雅黑: {
- normal: '微软雅黑.ttf',
- bold: '微软雅黑.ttf',
- italics: '微软雅黑.ttf',
- bolditalics: '微软雅黑.ttf',
- }
- };
3.Document-definition 对象中声明默认要使用的字体,具体来说:就是声明一个对象,除了 content 属性,还要有一个 defaultStyle 属性,该 defaultStyle 下面还有再有一个 font 属性:
- var dd = {
- content: [
- '中英文测试',
- 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'
- ],
- defaultStyle: {
- font: '微软雅黑'
- }
- };
以下为根据如上步骤做的一个完整例子源码:
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="utf-8">
- <title>
- my first export PDF
- </title>
- <script src="build/pdfmake.min.js">
- </script>
- <script src="build/vfs_fonts.js">
- </script>
- <script>
- function down() {
- var dd = {
- content: ['中英文测试', 'Another paragraph, this time a little bit longer to make sure, this line will be divided into at least two lines'],
- defaultStyle: {
- font: '微软雅黑'
- }
- };
- pdfMake.fonts = {
- Roboto: {
- normal: 'Roboto-Regular.ttf',
- bold: 'Roboto-Medium.ttf',
- italics: 'Roboto-Italic.ttf',
- bolditalics: 'Roboto-Italic.ttf'
- },
- 微软雅黑: {
- normal: '微软雅黑.ttf',
- bold: '微软雅黑.ttf',
- italics: '微软雅黑.ttf',
- bolditalics: '微软雅黑.ttf',
- }
- };
- pdfMake.createPdf(dd).download();
- }
- </script>
- </head>
- <body>
- <button onclick="down()">
- 下载
- </button>
- </body>
- </html>
插入图片
在插入图片方面,jsPDF 要求先将图片转换成 Data URL 才行,而 pdfmake 允许直接指定路径,看起来是很方便,但这是有条件的,必须是以 node.js 作为服务器,或者将图片放到 vfs_fonts.js 中,所以总的来说,用处不大,还是一样得将图片转换成 Data URL 形式才行。
为解决此问题,我写了一个 ImageDataURL 的函数对象,可同时传入多个图片地址。在图片都加载完成后,ImageDataURL.oncomplete 将被触发,在回调中通过 this.imgdata 取出各个图片的 Data URL,根据 pdfmake 的要求组织下,就可正确生成 pdf 了。
ImageDataURL 的原理是通过 H5 的 canvas 标签,将图片绘制在 canvas 上,然后通过 canvas 的 toDataURL 得到图像的 Data URL。使用时请注意浏览器兼容性问题。
以下为将 sampleImage.jpg, sampleage.jpg, sampleImage.jpg 依次写入 PDF 的例子,测试时 sampleage.jpg 不存在,PDF 直接忽略。
- <!DOCTYPE html>
- <html lang="zh-CN">
- <head>
- <meta charset="utf-8">
- <title>
- my second export PDF
- </title>
- <script src="build/pdfmake.min.js">
- </script>
- <script src="build/vfs_fonts.js">
- </script>
- <script>
- function down() {
- var x = new ImageDataURL(["sampleImage.jpg", "samplage.jpg", "sampleImage.jpg"]);
- x.oncomplete = function() {
- var imgs = new Array();
- console.log("complete");
- for (key in this.imgdata) {
- if (this.imgdata[key] == this.emptyobj) //不存在的图片直接忽略
- continue;
- imgs.push({
- image: this.imgdata[key]
- }); //pdfmake的图片格式{image:image dataurl}
- }
- var dd = {
- content: ['Title', imgs, ],
- };
- pdfMake.createPdf(dd).download();
- }
- }
- </script>
- </head>
- <body>
- <button onclick="down()">
- 下载
- </button>
- <script>
- function ImageDataURL(urls) { //urls必须是字符串或字符串数组
- this.completenum = 0;
- this.totalnum = 0;
- this.imgdata = new Array();
- this.emptyobj = new Object();
- this.oncomplete = function() {};
- this.getDataURL = function(url, index) {
- var c = document.createElement("canvas");
- var cxt = c.getContext("2d");
- var img = new Image();
- var dataurl;
- var p;
- p = this;
- img.src = url;
- img.onload = function() {
- var i;
- var maxwidth = 500;
- var scale = 1.0;
- if (img.width > maxwidth) {
- scale = maxwidth / img.width;
- c.width = maxwidth;
- c.height = Math.floor(img.height * scale);
- } else {
- c.width = img.width;
- c.height = img.height;
- }
- cxt.drawImage(img, 0, 0, c.width, c.height);
- p.imgdata[index] = c.toDataURL('image/jpeg');
- for (i = 0; i < p.totalnum; ++i) {
- if (p.imgdata[i] == null) break;
- }
- if (i == p.totalnum) {
- p.oncomplete();
- }
- };
- img.onerror = function() {
- p.imgdata[index] = p.emptyobj;
- for (i = 0; i < p.totalnum; ++i) {
- if (p.imgdata[i] == null) break;
- }
- if (i == p.totalnum) {
- p.oncomplete();
- }
- };
- }
- if (urls instanceof Array) {
- this.totalnum = urls.length;
- this.imgdata = new Array(this.totalnum);
- for (key in urls) {
- this.getDataURL(urls[key], key);
- }
- } else {
- this.imgdata = new Array(1);
- this.totalnum = 1;
- this.getDataURL(urls, 0);
- }
- }
- </script>
- </body>
- </html>
以上这篇 JS 导出 PDF 插件的方法 (支持中文、图片使用路径) 就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持 phperz。
来源: http://www.phperz.com/article/17/0305/264334.html