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 相关文章推荐
面向对象的编程思想在javascript中的运用上部
Nov 20 Javascript
JavaScript高级程序设计 错误处理与调试学习笔记
Sep 10 Javascript
javascript阻止浏览器后退事件防止误操作清空表单
Nov 22 Javascript
require.js深入了解 require.js特性介绍
Sep 04 Javascript
javascript实时显示北京时间的方法
Mar 12 Javascript
举例简介AngularJS的内部语言环境
Jun 17 Javascript
webix+springmvc session超时跳转登录页面
Oct 30 Javascript
javascript 产生随机数的几种方法总结
Sep 26 Javascript
vue.js 实现输入框动态添加功能
Jun 25 Javascript
在VUE style中使用data中的变量的方法
Jun 19 Javascript
完美解决通过IP地址访问VUE项目的问题
Jul 18 Javascript
八种Vue组件间通讯方式合集(推荐)
Aug 18 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制作静态网站的模板框架(二)
2006/10/09 PHP
php中$this-&amp;gt;含义分析
2009/11/29 PHP
linux下为php添加curl扩展的方法
2011/07/29 PHP
PHP中的str_repeat函数在JavaScript中的实现
2013/09/16 PHP
PHP实现根据设备类型自动跳转相应页面的方法
2014/07/24 PHP
PHP读取目录树的实现方法分析
2019/03/22 PHP
window.onload 加载完毕的问题及解决方案(下)
2009/07/09 Javascript
有效的捕获JavaScript焦点的方法小结
2009/10/08 Javascript
JQuery中extend的用法实例分析
2015/02/08 Javascript
JavaScript使用FileSystemObject对象写入文本文件内容的方法
2015/08/05 Javascript
vue2.0 自定义日期时间过滤器
2017/06/07 Javascript
Javascript es7中比较实用的两个方法示例
2017/07/21 Javascript
js中apply与call简单用法详解
2017/11/06 Javascript
详解Node 定时器
2018/02/26 Javascript
小程序图片长按识别功能的实现方法
2018/08/30 Javascript
Javascript中绑定click事件的四种方式介绍
2018/10/26 Javascript
小程序云开发获取不到数据库记录的解决方法
2019/05/18 Javascript
python rsa 加密解密
2017/03/20 Python
Python入门必须知道的11个知识点
2018/03/21 Python
Python登录系统界面实现详解
2019/06/25 Python
pandas将多个dataframe以多个sheet的形式保存到一个excel文件中
2019/10/10 Python
python爬虫可以爬什么
2020/06/16 Python
python利用appium实现手机APP自动化的示例
2021/01/26 Python
利用CSS3的特性改变文本选中时的颜色
2013/09/11 HTML / CSS
三星新西兰官网:Samsung新西兰
2019/03/05 全球购物
Contém1g官网:巴西彩妆品牌
2020/01/17 全球购物
幼师自荐信
2013/10/26 职场文书
奥巴马获胜演讲稿
2014/05/15 职场文书
施工质量承诺书范文
2014/05/30 职场文书
社区爱国卫生月活动总结
2014/06/30 职场文书
私人委托书格式
2014/09/10 职场文书
基层干部群众路线教育实践活动个人对照检查材料
2014/09/23 职场文书
对照检查剖析材料
2014/09/30 职场文书
创业计划书之川味火锅店
2019/09/02 职场文书
Win10 Anaconda安装python-pcl
2022/04/29 Servers
JDK8中String的intern()方法实例详细解读
2022/09/23 Java/Android