使用 HTML + JavaScript 实现手写签名功能(附完整代码)
在数字化办公和移动互联网时代,电子签名已成为不可或缺的功能之一。本文将详细介绍一个使用 HTML、CSS 和 JavaScript 实现的手写签名功能,让用户可以在网页上直接进行手写签名并保存为图片。
效果演示
本系统提供了一个简洁美观的手写签名界面,主要包括以下几个部分:顶部标题栏显示“手写签名”,中间区域是米字格书写区域,带有范字提示,底部控制按钮包括“清空重写”和“下载保存”。用户可以直接在米字格区域内进行手写签名,系统会实时记录用户的笔迹轨迹。完成签名后,可以一键清除重写或者下载保存为 PNG 图片。

页面结构
系统主要包括以下几个功能区域:
手写区域
本区域包含两个 canvas 的容器,采用相对定位;#guide 作为底稿层显示米字格和范字;#user 作为用户手写层接收用户输入。
<div id="paper">
<canvas id="guide"></canvas>
<canvas id="user"></canvas>
</div>
控制区域
本区域采用水平居中的布局设计,包含两个主要功能按钮:清空重写按钮 (#clearBtn) ,清除用户在手写层上的所有手写内容;下载保存按钮 (#downBtn),将用户签名保存为 PNG 图片文件
<div class="ctrl">
<button id="clearBtn">清空重写</button>
<button id="downBtn">下载保存</button>
</div>
核心功能实现
初始化配置
系统首先定义了详细的配置参数,包括范字字符串、网格规格、线条样式等。然后根据配置自动计算出行数和总尺寸,并设置画布大小。
var CONFIG = {
chars: '技术小丁', // 范字字符串
cols: 4, // 每行格数
cellPx: 180, // 每格像素
lineW: 2, // 米字/边框线宽
guideColor: 'rgba(180,180,180,.5)', // 底稿颜色
userColor: '#000000', // 用户笔迹颜色
penWidth: 5, // 笔尖宽度
};
var rows = Math.ceil(CONFIG.chars.length / CONFIG.cols);
var W = CONFIG.cellPx * CONFIG.cols;
var H = CONFIG.cellPx * rows;
document.getElementById('paper').style.width = W + 'px';
document.getElementById('paper').style.height = H + 'px';
绘制米字格底稿
gCtx.lineWidth = CONFIG.lineW;
gCtx.strokeStyle = CONFIG.guideColor;
gCtx.font = `${CONFIG.cellPx * 0.75}px 楷体`;
gCtx.textAlign = 'center';
gCtx.textBaseline = 'middle';
for (var i = 0; i < CONFIG.chars.length; i++) {
var r = Math.floor(i / CONFIG.cols);
var c = i % CONFIG.cols;
var x = c * CONFIG.cellPx;
var y = r * CONFIG.cellPx;
var cx = x + CONFIG.cellPx / 2;
var cy = y + CONFIG.cellPx / 2;
// 米字格
gCtx.beginPath();
gCtx.rect(x, y, CONFIG.cellPx, CONFIG.cellPx); // 外框
gCtx.moveTo(x, y);
gCtx.lineTo(x + CONFIG.cellPx, y + CONFIG.cellPx); // 左斜
gCtx.moveTo(x + CONFIG.cellPx, y);
gCtx.lineTo(x, y + CONFIG.cellPx); // 右斜
gCtx.moveTo(cx, y);
gCtx.lineTo(cx, y + CONFIG.cellPx);// 竖
gCtx.moveTo(x, cy);
gCtx.lineTo(x + CONFIG.cellPx, cy);// 横
gCtx.stroke();
// 范字
gCtx.strokeText(CONFIG.chars[i], cx, cy);
}
实现手写功能
uCtx.strokeStyle = CONFIG.userColor;
uCtx.lineWidth = CONFIG.penWidth;
uCtx.lineCap = uCtx.lineJoin = 'round';
var drawing = false, lastX, lastY;
function pos(e) {
var rect = uCanvas.getBoundingClientRect();
var x = (e.touches ? e.touches[0].clientX : e.clientX) - rect.left;
var y = (e.touches ? e.touches[0].clientY : e.clientY) - rect.top;
return [x, y];
}
function start(e) {
drawing = true;
[lastX, lastY] = pos(e);
uCtx.beginPath();
uCtx.moveTo(lastX, lastY);
}
function move(e) {
if (!drawing) return;
var [x, y] = pos(e);
uCtx.quadraticCurveTo(lastX, lastY, (lastX + x) / 2, (lastY + y) / 2);
uCtx.stroke();
[lastX, lastY] = [x, y];
}
function stop() {
drawing = false;
}
完整代码
https://gitee.com/ironpro/hjdemo/blob/master/handwritten/index.html
0 条评论
Java软件开发
- 从业日期: 2022/08/04
- 性别: 男
每天搬一点,幸福多一点
发帖数
源码数
接单
获赞
获评
{{commentItem.nickName}}
{{formatIntervalTime(commentItem.createTime)}}{{childComment.nickName}} {{childComment.replyNickName}}
{{formatIntervalTime(childComment.createTime)}}