分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > IT知识

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

发布时间:2023-09-06 01:48责任编辑:白小东关键词:暂无标签
原文:JS导出PDF插件(支持中文、图片使用路径)

在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>

参考

  • pdfmake如何使用自定义的字体
  • pdfmake的项目
  • pdfmake演示

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

原文地址:https://www.cnblogs.com/lonelyxmas/p/8744205.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved