使用 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 条评论

当前评论已经关闭


登录用户头像