JS导出PDF插件的方法(支持中文、图片使用路径)


Posted in Javascript onJuly 12, 2016

在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插件的方法(支持中文、图片使用路径)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
jquery插件 autoComboBox 下拉框
Dec 22 Javascript
用方法封装javascript的new操作符(一)
Dec 25 Javascript
JAVASCRIPT函数作用域和提前声明 分享
Aug 22 Javascript
Jquery Uploadify上传带进度条的简单实例
Feb 12 Javascript
现如今最流行的JavaScript代码规范
Mar 08 Javascript
node.js中的fs.readFile方法使用说明
Dec 15 Javascript
javascript引用类型之时间Date和数组Array
Aug 27 Javascript
详解require.js配置路径的用法和css的引入
Sep 06 Javascript
微信小程序实现简单跑马灯效果
May 26 Javascript
vuex 实现getter值赋值给vue组件里的data示例
Nov 05 Javascript
Vue插槽_特殊特性slot,slot-scope与指令v-slot说明
Sep 04 Javascript
JavaScript嵌入百度地图API的最详细方法
Apr 16 Javascript
浅谈angularJS中的事件
Jul 12 #Javascript
深入剖析JavaScript面向对象编程
Jul 12 #Javascript
JS及PHP代码编写八大排序算法
Jul 12 #Javascript
微信支付 JS API支付接口详解
Jul 11 #Javascript
判断输入的字符串是否是日期格式的简单方法
Jul 11 #Javascript
JS判断日期格式是否合法的简单实例
Jul 11 #Javascript
深入浅析JavaScript中的scrollTop
Jul 11 #Javascript
You might like
解析php中用PHPMailer来发送邮件的示例(126.com的例子)
2013/06/24 PHP
Discuz批量替换帖子内容的方法(使用SQL更新数据库)
2014/06/23 PHP
php基础教程
2015/08/26 PHP
yii框架搜索分页modle写法
2016/12/19 PHP
基于CI(CodeIgniter)框架实现购物车功能的方法
2018/04/09 PHP
一个符号插入器 中用到的js代码
2007/09/04 Javascript
按给定几率进行随机抽取的js代码
2010/12/28 Javascript
javascript 拖动表格行实现代码
2011/05/05 Javascript
Javascript弹出窗口的各种方法总结
2013/11/11 Javascript
解析prototype,JQuery中跳出each循环的方法
2013/12/12 Javascript
禁止页面刷新让F5快捷键及右键都无效
2014/01/22 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
2015/04/15 Javascript
jQuery动态效果显示人物结构关系图的方法
2015/05/07 Javascript
js同源策略详解
2015/05/21 Javascript
IE8 内存泄露(内存一直增长 )的原因及解决办法
2016/04/06 Javascript
js 能实现监听F5页面刷新子iframe 而父页面不刷新的方法
2016/11/09 Javascript
Vue键盘事件用法总结
2017/04/18 Javascript
js与jQuery实现的用户注册协议倒计时功能实例【三种方法】
2017/11/09 jQuery
Python随机生成手机号、数字的方法详解
2017/07/21 Python
遗传算法之Python实现代码
2017/10/10 Python
python爬虫爬取快手视频多线程下载功能
2018/02/28 Python
Python中pillow知识点学习
2018/04/30 Python
更新修改后的Python模块方法
2019/03/03 Python
pyqt5移动鼠标显示坐标的方法
2019/06/21 Python
Python列表的切片实例讲解
2019/08/20 Python
Python高级编程之消息队列(Queue)与进程池(Pool)实例详解
2019/11/01 Python
Python 解码Base64 得到码流格式文本实例
2020/01/09 Python
python3 配置logging日志类的操作
2020/04/08 Python
详解Pycharm与anaconda安装配置指南
2020/08/25 Python
html特殊符号示例 html特殊字符编码对照表
2014/01/14 HTML / CSS
阿德的梦教学反思
2014/02/06 职场文书
网络编辑岗位职责范本
2014/02/10 职场文书
教师党的群众路线教育实践活动剖析材料
2014/10/09 职场文书
企业内部管理控制:银行存款控制制度范本
2020/01/10 职场文书
CSS3实现三角形不断放大效果
2021/04/13 HTML / CSS
Python 正则模块详情
2021/11/02 Python