如何使用JavaScript库构建Webscript以生成手签PDF文件

414 阅读5分钟

使用JavaScript库构建Webscript以生成手写的PDF文件

在本教程中,我们将学习如何使用开源的JavaScript库将网页转换成PDF文档。手签是认证官方文件的一个好方法。

如果有关各方相距甚远怎么办?我们必须想办法让他们能够在线签署文件。

好在,我们可以使用一个名为Signature Pad的开源JavaScript库,不费吹灰之力就能在我们的Web应用程序中做到这一点。

我们将建立一个简单的发票,其中有一个嵌入的部分,一个人的签名将在签署后出现。稍后,我们将使用另一个名为jsPDF的开源库将网页转换为PDF文档。

我们的最终输出应该是这样的。

Generated pdf

前提条件

作为先决条件,读者必须具备以下条件。

  • 对HTML和CSS的理解。
  • 对JavaScript和文档对象操作(DOM)的了解。

目标

我们将学习。

  • 为网络应用程序创建一个签名功能。
  • 使用jsPDF库生成PDF。
  • 将生成的签名转换为图像。

这两个库的概述

签名板

签名板允许我们在画布元素上绘制平滑的曲线。这种能力使它适合于为终端用户创建一个签名板。

签名板提供了撤销、清除、改变曲线颜色、将签名转换为不同的图像格式,如.png.jpeg.svg ,等等的功能。

在我们的文章中,我们将把签名转换为.png 图像。

jsPDF

jsPDF用于从网页中生成一个PDF文档。它提供了设置字体类型、字体大小、线宽、文本颜色等选项。

然而,我们不会深入研究它的用途。我们将简单地用它来生成一个PDF。我将把其他功能留给你,让你通过结尾处的链接进行研究。

就这样,让我们首先设计一个页面的布局。

实施

页面布局

在本教程中,我们将使用Bootstrap库来设计网页。

我们将使用的主要Bootstrap样式类是。

  • col-md-* 一个页面的网格划分。这种风格设计将一个页面分成12列。例如,如果你想让某个元素覆盖页面宽度的三分之一,你可以使用 类。col-md-4
  • d-flex- 这允许我们使一个元素符合CSS的flexbox属性,我们将使用justify-content-* 定位来安排页面上的项目。如果我们想让div 的元素处于中心位置,我们将使用d-flex justify-content-center 类。

让我们简单地看一下这些组件。

<head> 将字符代码设置为UTF-8 ,页面的标题,以及链接到Bootstrap的风格设计。

<head>
  <meta charset="utf-8" />
  <title>Signature pad HTML2PDF</title>
  <link
    rel="stylesheet"
    href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
    integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
    crossorigin="anonymous"
  />
</head>

我们前往<body> 部分,其中有几个<div> 元素,我们将只看其中重要的元素。

我们将onselectstart 属性设置为返回false,这样我们就可以只在我们的canvas 上进行选择。

  • 第二个<div> ,包含表格和签名出现的区域。
<div id="toPrint" class="col-md-12">
  <table class="table">
    <thead class="thead-dark">
      <tr>
        <th scope="col"></th>
        <th scope="col">Item</th>
        <th scope="col">Price</th>
        <th scope="col">Quantity</th>
        <th scope="col">Price</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <th scope="row">1</th>
        <td>Toothbrush</td>
        <td>KES. 180</td>
        <td>3</td>
        <td>KES. 540</td>
      </tr>
      <tr>
        <th scope="row">2</th>
        <td>Toothpaste</td>
        <td>KES. 560</td>
        <td>1</td>
        <td>KES. 560</td>
      </tr>
      <tr>
        <th scope="row">3</th>
        <td>Cookies</td>
        <td>KES. 120</td>
        <td>2</td>
        <td>KES. 240</td>
      </tr>
      <tr>
        <th scope="row"></th>
        <td></td>
        <td></td>
        <th class="text-danger">GRAND TOTAL</th>
        <td>KES. 1340</td>
      </tr>
    </tbody>
  </table>
  <div class="col-md-12 d-flex justify-content-end">
    <div class="col-md-3 d-flex justify-content-center">
      <span class=" mb-4">Your Signature</span>
    </div>
  </div>
  <div class="col-md-12 d-flex justify-content-end">
    <div class="col-md-3 d-flex justify-content-center">
      <img
        id="signature"
        style="border: 1px solid black;"
        width="250px"
        height="100px"
      />
    </div>
  </div>
</div>
  • 下一个div ,包含画布元素,我们允许用户在这里画出签名。
<div class="col-md-12 d-flex justify-content-center ">
  <span class="col-md-3 mb-4">Sign here</span>
</div>
<div class="col-md-12 d-flex justify-content-center ">
  <canvas
    id="canvas"
    height="500"
    width="800"
    style="border: 1px solid black"
  ></canvas>
</div>
  • 最后一个div ,包含四个动作按钮,用于处理签名(Save ),清除签名(Clear ),撤销签名(Undo ),以及生成PDF文档(Get PDF ),点击即可。
<div class="col-md-12 d-flex justify-content-around ">
  <button
    type="button"
    style="margin-top: 2%; margin-bottom: 3%"
    class="btn btn-dark"
    data-action="action-save"
  >
    Save
  </button>
  <button
    type="button"
    style="margin-top: 2%; margin-bottom: 3%"
    class="btn btn-dark"
    data-action="action-undo"
  >
    Undo
  </button>
  <button
    type="button"
    style="margin-top: 2%; margin-bottom: 3%"
    class="btn btn-dark"
    data-action="action-clear"
  >
    Clear
  </button>
  <button
    type="button"
    style="margin-top: 2%; margin-bottom: 3%"
    class="btn btn-dark"
    data-action="action-pdf"
  >
    Get PDF
  </button>
</div>

注意脚本和样式标签,我们将在这里引用JavaScript和Bootstrap的样式文件。

在下一节中,我们将看看我们如何在按钮点击后用JavaScript执行动作。

JavaScript代码

你可以创建一个文件,并将其命名为sign-handler.js 或任何其他名称,只要你更新HTML代码的脚本引用。

我们将首先初始化用于访问DOM元素的变量。

var canvas = document.getElementById("canvas");
var saveSignBtn = document.querySelector("[data-action=action-save]");
var undoBtn = document.querySelector("[data-action=action-undo]");
var clearBtn = document.querySelector("[data-action=action-clear]");
var createPDFBtn = document.querySelector("[data-action=action-pdf]");
  • 接下来,我们初始化我们的SignaturePad 类,同时我们传入背景颜色为白色,并将画布设置为2D上下文。
var ourPad = new SignaturePad(canvas, {
  backgroundColor: "rgb(255, 255, 255)",
});

canvas.getContext("2d");
  • 之后,我们创建一个函数来创建一个blob。我们使用blob来获得一个图像路径,在这里我们设置图像的src
function processImage() {
  //creating a blob and displaying the image in the image element
  canvas.toBlob(function (blob) {
    var targetImg = document.querySelector("img"),
      url = URL.createObjectURL(blob);
    targetImg.src = url;
  });
}
  • 接下来的三个函数是直接的。它们是为了给三个按钮添加点击事件监听器。
    • saveSignBtn
    • clearBtn
    • undoBtn
  • 对于undo 按钮,我们使用pop() 函数删除画在画布上的最后一个点或曲线,然后使用fromData() 方法更新画布。
saveSignBtn.addEventListener("click", function (event) {
  if (ourPad.isEmpty()) {
    alert("Please sign first.");
  } else {
    processImage();
  }
});

//clearing the signature drawing
clearBtn.addEventListener("click", function (event) {
  if (ourPad.isEmpty()) {
    alert("Please sign first.");
  } else {
    ourPad.clear();
  }
});

undoBtn.addEventListener("click", function (event) {
  var signMark = ourPad.toData();
  if (ourPad.isEmpty()) {
    alert("Please sign first.");
  } else {
    if (signMark) {
      signMark.pop(); // deletinging the last marked dot or drawn line
      ourPad.fromData(signMark);
    }
  }
});
  • 最后,我们有按钮点击监听器函数来生成一个PDF文档。
//creating a pdf using the jsPDF library
createPDFBtn.addEventListener("click", function (event) {
  window.html2canvas = html2canvas;
  window.jsPDF = window.jspdf.jsPDF;
  var doc = new jsPDF("l", "pt", "a4");

  doc.html(document.getElementById("toPrint"), {
    callback: function (doc) {
      doc.save();
    },
    x: 10,
    y: 10,
  });
});

上面的代码做了以下工作。

  • 我们初始化html2canvasjsPDF 库。
  • 如果你想知道为什么我们要初始化html2canvas ,jsPDF库用它来捕捉页面的截图。
  • jsPDF 构造函数会传入方向(l 为横向)、测量单位(pt 为点)和A4尺寸。我们为我们的页面选择了横向纵向,以适应PDF文档。
  • html() 函数被调用,在这里我们传入要打印的元素和一个options 对象。
  • 该对象包含一个save() 回调函数,以保存PDF文档的XY 定位。还有一堆其他选项,你可以添加到这个对象中。

结论

最后,我们看了这两个库的概述,创建了一个HTML布局,并看了JavaScript代码。

你可以进一步加强这个签名功能,并将其用于生物识别认证。签名板库在你的React-Native应用、Web框架(如Express)、甚至桌面应用中都非常有用。