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 相关文章推荐
js中将具有数字属性名的对象转换为数组
Mar 06 Javascript
js字符串截取函数substr substring slice使用对比
Nov 27 Javascript
原生javascript实现拖动元素示例代码
Sep 01 Javascript
jQuery使用hide方法隐藏页面上指定元素的方法
Mar 30 Javascript
Jquery效果大全之制作电脑健康体检得分特效附源码下载
Nov 02 Javascript
uploadify多文件上传参数设置技巧
Nov 16 Javascript
学习JavaScript设计模式之责任链模式
Jan 18 Javascript
在页面中输出当前客户端时间javascript实例代码
Mar 02 Javascript
利用Angularjs实现幻灯片效果
Sep 07 Javascript
JSP防止网页刷新重复提交数据的几种方法
Nov 19 Javascript
vue中各选项及钩子函数执行顺序详解
Aug 25 Javascript
微信小程序日历/日期选择插件使用方法详解
Dec 28 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 vs Node.js
2015/07/17 PHP
thinkphp5框架结合mysql实现微信登录和自定义分享链接与图文功能示例
2019/08/13 PHP
一个js拖拽的效果类和dom-drag.js浅析
2010/07/17 Javascript
Javascript setInterval的两种调用方法(实例讲解)
2013/11/29 Javascript
js修改原型的属性使用介绍
2014/01/26 Javascript
详解js闭包
2014/09/02 Javascript
浅谈javascript语法和定时函数
2015/05/03 Javascript
jQuery实现带有上下控制按钮的简单多行滚屏效果代码
2015/09/04 Javascript
JS弹出新窗口被拦截的解决方法
2016/08/09 Javascript
详解能在多种前端框架下使用的表格控件
2017/01/11 Javascript
JavaScript中递归实现的方法及其区别
2017/09/12 Javascript
angularJS的radio实现单项二选一的使用方法
2018/02/28 Javascript
vue.js使用3DES加密的方法示例
2018/05/18 Javascript
对vue下点击事件传参和不传参的区别详解
2018/09/15 Javascript
Vue安装浏览器开发工具的步骤详解
2019/05/12 Javascript
[00:17]天涯墨客一技能展示
2018/08/25 DOTA
跟老齐学Python之Python文档
2014/10/10 Python
浅要分析Python程序与C程序的结合使用
2015/04/07 Python
Python编程给numpy矩阵添加一列方法示例
2017/12/04 Python
Python 16进制与中文相互转换的实现方法
2018/07/09 Python
对Python3.x版本print函数左右对齐详解
2018/12/22 Python
浅谈python str.format与制表符\t关于中文对齐的细节问题
2019/01/14 Python
Python 实现opencv所使用的图片格式与 base64 转换
2020/01/09 Python
Python利用逻辑回归模型解决MNIST手写数字识别问题详解
2020/01/14 Python
Django中F函数的使用示例代码详解
2020/07/06 Python
利用Python实现学生信息管理系统的完整实例
2020/12/30 Python
使用Filters滤镜弥补CSS3的跨浏览器问题以及兼容低版本IE
2013/01/23 HTML / CSS
REISS英国官网:伦敦High Street最受欢迎品牌
2016/12/21 全球购物
The North Face北面英国官网:美国著名户外品牌
2017/12/13 全球购物
美国和加拿大计算机和电子产品购物网站:TigerDirect.com
2019/09/13 全球购物
个人简历中自我评价
2014/02/11 职场文书
四风对照检查材料思想汇报
2014/09/20 职场文书
《工作是最好的修行》读后感3篇
2019/12/13 职场文书
详解redis分布式锁的这些坑
2021/05/19 Redis
Java SSH 秘钥连接mysql数据库的方法
2021/06/28 Java/Android
解决Python保存文件名太长OSError: [Errno 36] File name too long
2022/05/11 Python