JS導(dǎo)出PDF插件的方法(支持中文、圖片使用路徑)

字號:


    在WEB上想做一個導(dǎo)出PDF的功能,發(fā)現(xiàn)jsPDF比較多人推薦,遺憾的是不支持中文,最后找到pdfmake,很好地解決了此問題。它的效果可以先到http://pdfmake.org/playground.html查看。在使用過程中,還發(fā)現(xiàn)圖片的插入是相對繁瑣的一件事。
    針對這些問題,本文的主要內(nèi)容可分為三部分:
    •pdfmake的基本使用方法;
    •如何解決中文問題;
    •如何通過指定圖片地址插入圖片。
    pdfmake的基本使用方法
    1.包含以下兩個文件
    <script src="build/pdfmake.min.js"></script>
     <script src="build/vfs_fonts.js"></script>
    2.在JS代碼中聲明一個Document-definition對象,這個是pdfmake自己的術(shù)語。簡單點說,就是創(chuàng)建一個至少包含content屬性的對象。然后就可以調(diào)用pdfMake的方法導(dǎo)出PDF,具體見如下代碼:
    <script type="text/javascript">
     //創(chuàng)建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'
           ]
        };
     //導(dǎo)出PDF
     pdfMake.createPdf(dd).download();
     </script>
    按照上例操作,就可以看到提示文件下載了。關(guān)于pdfmake的完整教程請登陸pdfmake項目查看。
    pdfmake支持中文
    三個步驟:
    1.到pdfmake項目網(wǎng)站,把工程都下載下來,然后進入工程目錄將字體文件(比如微軟雅黑.ttf)放到examples/fonts目錄下,然后使用grunt dump_dir生成新的vfs_fonts.js文件;
    從上面描述可知該工程是通過grunt管理的,如果無相關(guān)知識,請上網(wǎng)先補習(xí)下。
    grunt dump_dir命令會將fonts目錄下所有文件都打包,因此無用文件請別放進去。
    微軟雅黑.ttf網(wǎng)上一搜一大把,WINDOWS電腦系統(tǒng)盤下存放字體的目錄也找得到。
    2.回到自己的例子代碼中,JS代碼中修改pdfMake的fonts對象,聲明當(dāng)前要用到字體:
    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對象中聲明默認(rèn)要使用的字體,具體來說:就是聲明一個對象,除了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: '微軟雅黑'
           }
        };
    以下為根據(jù)如上步驟做的一個完整例子源碼:
    <!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要求先將圖片轉(zhuǎn)換成Data URL才行,而pdfmake允許直接指定路徑,看起來是很方便,但這是有條件的,必須是以node.js作為服務(wù)器,或者將圖片放到vfs_fonts.js中,所以總的來說,用處不大,還是一樣得將圖片轉(zhuǎn)換成Data URL形式才行。
    為解決此問題,我寫了一個ImageDataURL的函數(shù)對象,可同時傳入多個圖片地址。在圖片都加載完成后,ImageDataURL.oncomplete將被觸發(fā),在回調(diào)中通過this.imgdata取出各個圖片的Data URL,根據(jù)pdfmake的要求組織下,就可正確生成pdf了。
    ImageDataURL的原理是通過H5的canvas標(biāo)簽,將圖片繪制在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必須是字符串或字符串?dāng)?shù)組
        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導(dǎo)出PDF插件的方法(支持中文、圖片使用路徑)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考