当前位置: 代码网 > it编程>编程语言>Javascript > JavaScript实现签名板功能

JavaScript实现签名板功能

2024年11月26日 Javascript 我要评论
签名板在网页应用中扮演着重要角色,它们能够记录用户的手写签名或者绘图,从而提升了用户体验。在接下来的内容中,我将指导你如何利用 javascript 来开发一个功能丰富的签名板。这个签名板不仅支持自定

签名板在网页应用中扮演着重要角色,它们能够记录用户的手写签名或者绘图,从而提升了用户体验。

在接下来的内容中,我将指导你如何利用 javascript 来开发一个功能丰富的签名板。这个签名板不仅支持自定义和响应式设计,还具备对触摸设备的兼容、多样的笔触样式选择,以及将签名导出为不同格式图片的能力。此外,我们还将探索如何整合像 signature_pad 这样的先进工具来增强签名板的功能。

开始

让我们使用纯 html、css 和 javascript 创建一个简单的签名板。

首先,html 文件——在你的工作目录中创建一个 index.html 文件:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>javascript签名板</title>
    <link rel="stylesheet" href="styles.css" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >
  </head>
  <body>
    <div class="signature-container">
      <canvas id="signature-pad" width="400" height="200"></canvas>
      <button id="clear">清除</button>
    </div>
    <script src="script.js"></script>
  </body>
</html>

我们将采用 <canvas> 标签来构建签名板。选择画布作为工具是因为它为我们提供了以下功能:

  • 利用 javascript 实现自由手写,这对于获取签名是必不可少的。
  • 对画布的外观和行为进行个性化定制,包括线条的颜色、粗细以及风格。
  • 兼容多样的鼠标和触摸事件,捕捉用户在绘图、移动以及提笔或松手时的互动。
  • 利用 todataurl 方法将签名以图像形式导出(如 png 或 jpeg),这在保存签名或将其上传至服务器时非常有用。

接下来,我们将通过 styles.css 为这个页面添加一些样式,以提升其视觉效果。

body {
  display: flex;
  justify - content: center;
  align - items: center;
  height: 100vh;
  background - color: #f0f0f0;
  margin: 0;
}

.signature - container {
  display: flex;
  flex - direction: column;
  align - items: center;
}

canvas {
  border: 1px solid#000;
  background - color: #fff;
}

button {
  margin - top: 10px;
  padding: 5px 10px;
  cursor: pointer;
}

然后向目录中添加一个 script.js 文件:

document.addeventlistener('domcontentloaded',
function() {
  var canvas = document.getelementbyid('signature-pad');
  var ctx = canvas.getcontext('2d');
  var drawing = false;
  canvas.addeventlistener('mousedown',
  function(e) {
    drawing = true;
    ctx.beginpath();
    ctx.moveto(e.offsetx, e.offsety);
  });
  canvas.addeventlistener('mousemove',
  function(e) {
    if (drawing) {
      ctx.lineto(e.offsetx, e.offsety);
      ctx.stroke();
    }
  });
  canvas.addeventlistener('mouseup',
  function() {
    drawing = false;
  });
  canvas.addeventlistener('mouseout',
  function() {
    drawing = false;
  });
  document.getelementbyid('clear').addeventlistener('click',
  function() {
    ctx.clearrect(0, 0, canvas.width, canvas.height);
  });
});

让我们详细解释一下这段代码的工作原理:

  • 我们首先通过 canvas 变量来绑定到页面上的 <canvas> 元素。
  • 接着,ctx 变量用于获取该画布的 2d 渲染上下文,它包含了绘制图形所需的各种方法和属性。
  • 当用户按下鼠标按钮时,我们通过一个 mousedown 事件监听器来触发绘图动作。此时,ctx.beginpath() 用于开启新的绘图路径,而 ctx.moveto(e.offsetx, e.offsety) 则将画笔定位到鼠标点击的准确位置。
  • 用户移动鼠标时,mousemove 事件监听器会根据鼠标的当前位置绘制线条。ctx.lineto(e.offsetx, e.offsety) 命令画笔绘制一条直线到新位置,随后 ctx.stroke() 将这条线实际画到画布上。
  • 为了结束绘图,我们设置了 mouseup 和 mouseout 两个事件监听器,分别在鼠标按钮释放和鼠标光标移出画布时停止绘图。此外,当用户点击清除按钮时,ctx.clearrect(0, 0, canvas.width, canvas.height); 用于清除整个画布,为新的绘图做准备。

添加触摸支持

这个示例主要是为鼠标事件设置的,但它也可以很容易地扩展到支持触摸设备。以下是 javascript 处理触摸事件:

document.addeventlistener('domcontentloaded',
function() {
  var canvas = document.getelementbyid('signature-pad');
  var ctx = canvas.getcontext('2d');
  var drawing = false;

  function startdrawing(e) {
    drawing = true;
    ctx.beginpath();
    ctx.moveto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
      ctx.stroke();
    }
  }

  function stopdrawing() {
    drawing = false;
  }

  // 鼠标事件
  canvas.addeventlistener('mousedown', startdrawing);
  canvas.addeventlistener('mousemove', draw);
  canvas.addeventlistener('mouseup', stopdrawing);
  canvas.addeventlistener('mouseout', stopdrawing);

  // 触摸事件
  canvas.addeventlistener('touchstart', startdrawing);
  canvas.addeventlistener('touchmove', draw);
  canvas.addeventlistener('touchend', stopdrawing);
  canvas.addeventlistener('touchcancel', stopdrawing);

  document.getelementbyid('clear').addeventlistener('click',
  function() {
    ctx.clearrect(0, 0, canvas.width, canvas.height);
  });
});

对于触摸事件,使用 e.touches[0].clientxe.touches[0].clienty 来获取触摸坐标。为了考虑画布的位置,使用 canvas.offsetleftcanvas.offsettop 进行调整:

自定义

让我们给签名板增添一些新功能,比如让用户能够挑选不同的笔触效果。为此,我们将执行以下关键步骤:

  • 在 html 代码中嵌入一个 <select> 标签,它将包含两个选项:pen 和 brush,从而让用户可以挑选他们喜欢的笔触风格。
  • 为这些新增的控件编写相应的 css 样式,确保它们在页面上正确地显示。
  • 为下拉选择菜单设置一个事件监听器,以便在用户选择不同的选项时,动态地改变笔触样式。
  • 根据用户所选择的笔触样式,调整 ctx.linewidth(线宽)和 ctx.linecap(线帽形状)的值,以反映不同的视觉效果。

以下是需要添加到 html 文件中的代码片段:

<div class="controls">
  <select id="stroke-style">
    <option value="pen">
      钢笔
    </option>
    <option value="brush">
      刷子
    </option>
  </select>
  <button id="clear">
    javascript签名板
  </button>
</div>

然后我们更新我们的 css:

body {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
    background-color: #f0f0f0;
    margin: 0;
}

.signature-container {
    display: flex;
    flex-direction: column;
    align-items: center;
}

canvas {
    border: 1px solid #000;
    background-color: #fff;
}

.controls {
    margin-top: 10px;
    display: flex;
    gap: 10px;
}

button, select {
    padding: 5px 10px;
    cursor: pointer;
}

最后,更新 script.js

document.addeventlistener('domcontentloaded',
function() {
  var canvas = document.getelementbyid('signature-pad');
  var ctx = canvas.getcontext('2d');
  var drawing = false;
  var strokestyle = 'pen';

  function startdrawing(e) {
    drawing = true;
    ctx.beginpath();
    ctx.moveto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
      ctx.stroke();
    }
  }

  function stopdrawing() {
    drawing = false;
  }

  // 鼠标事件
  canvas.addeventlistener('mousedown', startdrawing);
  canvas.addeventlistener('mousemove', draw);
  canvas.addeventlistener('mouseup', stopdrawing);
  canvas.addeventlistener('mouseout', stopdrawing);

  // 触摸事件
  canvas.addeventlistener('touchstart', startdrawing);
  canvas.addeventlistener('touchmove', draw);
  canvas.addeventlistener('touchend', stopdrawing);
  canvas.addeventlistener('touchcancel', stopdrawing);

  document.getelementbyid('clear').addeventlistener('click',
  function() {
    ctx.clearrect(0, 0, canvas.width, canvas.height);
  });

  document.getelementbyid('stroke-style').addeventlistener('change',
  function(e) {
    strokestyle = e.target.value;
    if (strokestyle === 'pen') {
      ctx.linewidth = 2;
      ctx.linecap = 'round';
    } else if (strokestyle === 'brush') {
      ctx.linewidth = 5;
      ctx.linecap = 'round';
    }
  });

  // 设置初始笔画样式
  ctx.linewidth = 2;
  ctx.linecap = 'round';
});

处理响应性

当屏幕缩小时,签名板可能因为缺少响应式设计而无法正常工作。为了改善这一点,我们可以增强应用的响应性,使其在小屏幕设备上也能轻松进行签名操作。

关键在于确保画布及其容器能够灵活适应不同的屏幕尺寸。这需要我们根据浏览器窗口的大小来动态调整画布的尺寸。

具体来说,我们需要做出以下调整:

  • 为 .signature-container 设置一个灵活的宽度,比如占满90%的可用空间,并设定一个最大宽度限制,比如600像素。
  • 将画布元素的宽度设置为 width: 100%,高度设置为 height: auto,以实现响应式效果。

在 javascript 代码中,我们需要执行以下操作:

  • 创建一个名为 resizecanvas 的函数,用以根据其容器尺寸的变化来调整画布的大小。
  • 在页面加载时首先调用 resizecanvas 函数,并在窗口大小发生变化时添加一个事件监听器,确保画布能够随着窗口大小的变化而动态调整尺寸。

按照上述说明,我们需要更新 styles.css 文件,以实现所需的样式调整。

body {
  display: flex;
  justify - content: center;
  align - items: center;
  height: 100vh;
  background - color: #f0f0f0;
  margin: 0;
}

.signature - container {
  display: flex;
  flex - direction: column;
  align - items: center;
  width: 90 % ;
  max - width: 600px;
}

canvas {
  border: 1px solid#000;
  background - color: #fff;
  width: 100 % ;
  height: auto;
}

.controls {
  margin - top: 10px;
  display: flex;
  gap: 10px;
}

button,
select {
  padding: 5px 10px;
  cursor: pointer;
}

这是在添加之后 script.js 的样子:

document.addeventlistener('domcontentloaded',
function() {
  var canvas = document.getelementbyid('signature-pad');
  var ctx = canvas.getcontext('2d');
  var drawing = false;
  var strokestyle = 'pen';

  function resizecanvas() {
    canvas.width = canvas.offsetwidth;
    canvas.height = canvas.offsetheight;
    ctx.linewidth = strokestyle === 'pen' ? 2 : 5;
    ctx.linecap = 'round';
  }

  function startdrawing(e) {
    drawing = true;
    ctx.beginpath();
    ctx.moveto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
      ctx.stroke();
    }
  }

  function stopdrawing() {
    drawing = false;
  }

  // 鼠标事件
  canvas.addeventlistener('mousedown', startdrawing);
  canvas.addeventlistener('mousemove', draw);
  canvas.addeventlistener('mouseup', stopdrawing);
  canvas.addeventlistener('mouseout', stopdrawing);

  // 触摸事件
  canvas.addeventlistener('touchstart', startdrawing);
  canvas.addeventlistener('touchmove', draw);
  canvas.addeventlistener('touchend', stopdrawing);
  canvas.addeventlistener('touchcancel', stopdrawing);

  document.getelementbyid('clear').addeventlistener('click',
  function() {
    ctx.clearrect(0, 0, canvas.width, canvas.height);
  });

  document.getelementbyid('stroke-style').addeventlistener('change',
  function(e) {
    strokestyle = e.target.value;
    ctx.linewidth = strokestyle === 'pen' ? 2 : 5;
  });

  // 初始画布设置
  resizecanvas();
  window.addeventlistener('resize', resizecanvas);
});

你可能会观察到,当改变浏览器窗口大小时,画布上的签名会消失,这是因为调整画布尺寸会自动清除其内容。这是 <canvas> 元素的标准行为。不过,我们可以通过一些技巧来避免这个问题。

为了在缩放画布时保持签名的完整性,并且能够正确地对其进行缩放,我们需要先保存画布上的签名,然后在调整画布尺寸后再重新绘制它。我们可以通过 todataurl 方法来保存画布上的签名。

htmlcanvaselement.todataurl() 方法能够根据你指定的图片格式,将画布上的内容转换成一个数据 url。

现在,让我们来看一下如何保存签名,以便在窗口大小调整后可以将其恢复。我们需要做的调整如下:

  • 定义一个 signaturedata 变量来存储签名的当前状态,以数据 url 的形式。
  • 修改 resizecanvas 函数,使其能在调整画布大小时,先保存签名,再调整尺寸,并最终重新绘制签名。
  • 创建一个 image 对象来加载保存的签名,并在调整尺寸后的画布上将其恢复。
  • 当完成绘画时,使用 canvas.todataurl() 方法更新 signaturedata 变量,以便存储当前的画布内容。
  • 当用户点击清除按钮时,将 signaturedata 变量重置为 null,以清除保存的签名数据。

实施了上述更改后,我们的 javascript 文件将如下所示:

document.addeventlistener('domcontentloaded',
function() {
  var canvas = document.getelementbyid('signature-pad');
  var ctx = canvas.getcontext('2d');
  var drawing = false;
  var strokestyle = 'pen';
  var signaturedata = null;

  function resizecanvas() {
    if (signaturedata) {
      var img = new image();
      img.src = signaturedata;
      img.onload = function() {
        ctx.clearrect(0, 0, canvas.width, canvas.height);
        canvas.width = canvas.offsetwidth;
        canvas.height = canvas.offsetheight;
        ctx.drawimage(img, 0, 0, canvas.width, canvas.height);
        setstrokestyle();
      };
    } else {
      canvas.width = canvas.offsetwidth;
      canvas.height = canvas.offsetheight;
      setstrokestyle();
    }
  }

  function setstrokestyle() {
    if (strokestyle === 'pen') {
      ctx.linewidth = 2;
      ctx.linecap = 'round';
    } else if (strokestyle === 'brush') {
      ctx.linewidth = 5;
      ctx.linecap = 'round';
    }
  }

  function startdrawing(e) {
    drawing = true;
    ctx.beginpath();
    ctx.moveto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
      ctx.stroke();
    }
  }

  function stopdrawing() {
    drawing = false;
    signaturedata = canvas.todataurl();
  }

  // 鼠标事件
  canvas.addeventlistener('mousedown', startdrawing);
  canvas.addeventlistener('mousemove', draw);
  canvas.addeventlistener('mouseup', stopdrawing);
  canvas.addeventlistener('mouseout', stopdrawing);

  // 触摸事件
  canvas.addeventlistener('touchstart', startdrawing);
  canvas.addeventlistener('touchmove', draw);
  canvas.addeventlistener('touchend', stopdrawing);
  canvas.addeventlistener('touchcancel', stopdrawing);

  document.getelementbyid('clear').addeventlistener('click',
  function() {
    ctx.clearrect(0, 0, canvas.width, canvas.height);
    signaturedata = null;
  });

  document.getelementbyid('stroke-style').addeventlistener('change',
  function(e) {
    strokestyle = e.target.value;
    setstrokestyle();
  });

  // 初始画布设置
  resizecanvas();
  window.addeventlistener('resize', resizecanvas);
});

保存和导出

我们将进一步增强功能,允许用户将他们的签名以 png 或 jpeg 格式导出,且这些图片将拥有白色背景。为此,我们将执行以下步骤:

  • 在 html 代码中增加两个按钮,分别用于将签名导出为 png 和 jpeg 文件。
  • 开发一个名为 exportcanvas 的函数,该函数负责将画布内容(包括白色背景)导出。这一过程涉及到创建一个新画布,将白色填充为背景色,然后将当前签名绘制上去,最后将其保存为 png 或 jpeg 文件。

以下是经过这些更改后的 html 代码示例:

<!doctype html>
<html lang="en">
  
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
      javascript签名板
    </title>
    <link rel="stylesheet" href="styles.css" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >
  </head>
  
  <body>
    <div class="signature-container">
      <canvas id="signature-pad" width="400" height="200">
      </canvas>
      <div class="controls">
        <button id="clear">
          清除
        </button>
        <button id="export-png">
          导出png格式
        </button>
        <button id="export-jpeg">
          导出jpeg格式
        </button>
      </div>
    </div>
    <script src="script.js">
    </script>
  </body>

</html>

这是在添加之后 javascript 文件的样子:

document.addeventlistener('domcontentloaded',
function() {
  var canvas = document.getelementbyid('signature-pad');
  var ctx = canvas.getcontext('2d');
  var drawing = false;
  var strokestyle = 'pen';
  var signaturedata = null;

  function resizecanvas() {
    if (signaturedata) {
      var img = new image();
      img.src = signaturedata;
      img.onload = function() {
        ctx.clearrect(0, 0, canvas.width, canvas.height);
        canvas.width = canvas.offsetwidth;
        canvas.height = canvas.offsetheight;
        ctx.drawimage(img, 0, 0, canvas.width, canvas.height);
        setstrokestyle();
      };
    } else {
      canvas.width = canvas.offsetwidth;
      canvas.height = canvas.offsetheight;
      setstrokestyle();
    }
  }

  function setstrokestyle() {
    if (strokestyle === 'pen') {
      ctx.linewidth = 2;
      ctx.linecap = 'round';
    } else if (strokestyle === 'brush') {
      ctx.linewidth = 5;
      ctx.linecap = 'round';
    }
  }

  function startdrawing(e) {
    drawing = true;
    ctx.beginpath();
    ctx.moveto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
  }

  function draw(e) {
    if (drawing) {
      ctx.lineto(e.offsetx || e.touches[0].clientx - canvas.offsetleft, e.offsety || e.touches[0].clienty - canvas.offsettop);
      ctx.stroke();
    }
  }

  function stopdrawing() {
    drawing = false;
    signaturedata = canvas.todataurl();
  }

  function exportcanvas(format) {
    var exportcanvas = document.createelement('canvas');
    exportcanvas.width = canvas.width;
    exportcanvas.height = canvas.height;
    var exportctx = exportcanvas.getcontext('2d');

    // 用白色填充背景
    exportctx.fillstyle = '#fff';
    exportctx.fillrect(0, 0, exportcanvas.width, exportcanvas.height);

    // 绘制签名
    exportctx.drawimage(canvas, 0, 0);

    // 导出画布
    var dataurl = exportcanvas.todataurl(`image / $ {
      format
    }`);
    var link = document.createelement('a');
    link.href = dataurl;
    link.download = `signature.$ {
      format
    }`;
    link.click();
  }

  // 鼠标事件
  canvas.addeventlistener('mousedown', startdrawing);
  canvas.addeventlistener('mousemove', draw);
  canvas.addeventlistener('mouseup', stopdrawing);
  canvas.addeventlistener('mouseout', stopdrawing);

  // 触摸事件
  canvas.addeventlistener('touchstart', startdrawing);
  canvas.addeventlistener('touchmove', draw);
  canvas.addeventlistener('touchend', stopdrawing);
  canvas.addeventlistener('touchcancel', stopdrawing);

  document.getelementbyid('clear').addeventlistener('click',
  function() {
    ctx.clearrect(0, 0, canvas.width, canvas.height);
    signaturedata = null;
  });

  document.getelementbyid('stroke-style').addeventlistener('change',
  function(e) {
    strokestyle = e.target.value;
    setstrokestyle();
  });

  document.getelementbyid('export-png').addeventlistener('click',
  function() {
    exportcanvas('png');
  });

  document.getelementbyid('export-jpeg').addeventlistener('click',
  function() {
    exportcanvas('jpeg');
  });

  // 初始画布设置
  resizecanvas();
  window.addeventlistener('resize', resizecanvas);
});

添加更多功能

通过引入外部库,我们可以简化签名板中一些复杂功能的实现过程。我们将采用 signature_pad 这个库,它非常出色,能够帮助我们轻松地实现之前讨论过的众多功能,并且它还能让我们生成更加流畅的签名效果。

首先,我们需要在 html 文档中引入 signature_pad 库:

<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js"></script>

然后添加必要的按钮。这是最终 html 的样子:

<!doctype html>
<html lang="en">
  
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>
      javascript签名板
    </title>
    <link rel="stylesheet" href="styles.css" rel="external nofollow"  rel="external nofollow"  rel="external nofollow" >
    <script src="https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js">
    </script>
  </head>
  
  <body>
    <div class="signature-container">
      <canvas id="signature-pad" width="600" height="400">
      </canvas>
      <div class="controls">
        <button id="undo">
          撤销
        </button>
        <button id="redo">
          重做
        </button>
        <button id="clear">
          清除
        </button>
        <button id="save-png">
          导出png格式
        </button>
        <button id="save-jpeg">
          导出jpeg格式
        </button>
      </div>
    </div>
    <script src="script.js">
    </script>
  </body>

</html>

更新样式:

body {
  display: flex;
  justify - content: center;
  align - items: center;
  height: 100vh;
  background - color: #f0f0f0;
  margin: 0;
}

.signature - container {
  display: flex;
  flex - direction: column;
  align - items: center;
  width: 90 % ;
  max - width: 600px;
}

canvas {
  border: 1px solid#000;
  background - color: #fff;
  width: 100 % ;
  height: auto;
}

.controls {
  margin - top: 10px;
  display: flex;
  gap: 10px;
  flex - wrap: wrap;
}

button {
  padding: 5px 10px;
  cursor: pointer;
}

为了进一步完善我们的签名板功能,script.js 脚本需要进行以下更新:

  • 实现两个栈,undostack 和 redostack,分别用来追踪撤销和重做的历史状态。
  • 创建一个 savestate 函数,该函数负责将签名板的当前状态存储到撤销栈中。
  • 定义 undo 和 redo 函数,分别用于执行撤销和重做的操作。

经过这些修改,script.js 脚本将具备完整的撤销和重做功能。以下是更新后的 script.js 脚本:

document.addeventlistener('domcontentloaded',
function() {
  var canvas = document.getelementbyid('signature-pad');
  var signaturepad = new signaturepad(canvas);
  var undostack = [];
  var redostack = [];
  function savestate() {
    undostack.push(deepcopy(signaturepad.todata()));
    redostack = [];
  }
  function undo() {
    if (undostack.length > 0) {
      redostack.push(deepcopy(signaturepad.todata()));
      undostack.pop();
      signaturepad.clear();
      if (undostack.length) {
        var laststroke = undostack[undostack.length - 1];
        signaturepad.fromdata(laststroke, {
          clear: false
        });
      }
    }
  }
  function redo() {
    if (redostack.length > 0) {
      undostack.push(deepcopy(signaturepad.todata()));
      var nextstate = redostack.pop();
      signaturepad.clear();
      if (nextstate.length) {
        signaturepad.fromdata(nextstate);
      }
    }
  }
  document.getelementbyid('undo').addeventlistener('click', undo);
  document.getelementbyid('redo').addeventlistener('click', redo);
  document.getelementbyid('clear').addeventlistener('click',
  function() {
    signaturepad.clear();
    undostack = [];
    redostack = [];
  });
  document.getelementbyid('save-png').addeventlistener('click',
  function() {
    if (!signaturepad.isempty()) {
      var dataurl = signaturepad.todataurl('image/png');
      var link = document.createelement('a');
      link.href = dataurl;
      link.download = 'signature.png';
      link.click();
    }
  });
  document.getelementbyid('save-jpeg').addeventlistener('click',
  function() {
    if (!signaturepad.isempty()) {
      var dataurl = signaturepad.todataurl('image/jpeg');
      var link = document.createelement('a');
      link.href = dataurl;
      link.download = 'signature.jpeg';
      link.click();
    }
  });
  // 绘图结束时保存状态
  signaturepad.addeventlistener("endstroke", () = >{
    console.log("signature end");
    savestate();
  });
  // 初始画布设置
  function resizecanvas() {
    var ratio = math.max(window.devicepixelratio || 1, 1);
    canvas.width = canvas.offsetwidth * ratio;
    canvas.height = canvas.offsetheight * ratio;
    canvas.getcontext('2d').scale(ratio, ratio);
    signaturepad.clear(); // 否则 isempty() 可能会返回错误值
    if (undostack.length > 0) {
      signaturepad.fromdata(undostack[undostack.length - 1]);
    }
  }
  function deepcopy(data) {
    return json.parse(json.stringify(data));
  }
  window.addeventlistener('resize', resizecanvas);
  resizecanvas();
});

应用场景介绍:javascript 签名板

掌握上述代码能够让我们应对多种实际应用场景。

电子签名在网页表单中的应用

通过在网页表单中集成签名板,用户可以轻松地电子签名文档,这在处理合同、协议和同意书时尤为重要。在法律、房地产、医疗和金融等行业内,电子签名的收集成为工作流程中不可或缺的一环,有效减少了纸质文件的使用。

在线绘图工具的集成

开发者可以将签名板整合到需要用户进行绘图或注释的在线应用中。无论是协作白板、设计软件还是交互式反馈环节,签名板都能发挥重要作用。例如,在在线教育平台上,学生可以利用签名板在直播课程中绘制图表或解答数学题目,教师也能即时给予反馈。

网络文档和图像编辑器中的注释功能

签名板可作为网络文档和图像编辑器中的注释工具,让用户能够直接在文档或图像上添加手写注释、评论或草图。

访客登记管理

在访客登记管理中,签名板可用于记录访客的数字化签到和签出信息,这在企业管理和活动策划中非常实用。

总结

在本篇文章中,我们探索了如何使用纯 javascript 来创建一个功能丰富的签名板,包括触摸支持、笔触样式选择、响应式设计以及导出功能。我们学习了如何利用 html 的 <canvas> 元素来捕捉用户的手写签名,并通过 javascript 为签名板添加了撤销、重做等高级功能。此外,我们还通过引入 signature_pad 库进一步简化了开发过程,使得实现平滑的签名体验变得更加容易。

通过这些技术,我们不仅能够创建一个基本的签名板,还能够为其添加各种实用的功能,使其适应不同的应用场景。无论是在网页表单中收集电子签名,还是在在线教育平台中作为绘图工具,或是作为网络文档编辑器中的注释工具,javascript 签名板都能提供出色的用户体验。

此外,我们还讨论了如何将签名数据导出为不同格式的图片,这对于保存签名或将其发送到服务器进行进一步处理非常有用。例如,签名验证功能可以提高在线交易的安全性,确保用户的身份得到确认。

总的来说,javascript 签名板的灵活性和可定制性使其成为现代网络应用的理想选择。随着技术的不断进步,我们可以预见,javascript 签名板将在未来的网络应用中扮演越来越重要的角色,为用户提供更加丰富和便捷的手写签名体验。通过本文的指导,开发者可以轻松地在自己的项目中实现这些功能,无论是简单的签名收集还是复杂的交互式绘图和注释,都能轻松应对。这种技术的应用不仅提高了工作效率,也为用户带来了更加直观和个性化的交互方式。

以上就是javascript实现签名板功能的详细内容,更多关于javascript签名板的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com