电子签名组件 Signature Pad 介绍
🔍 一、Signature Pad 核心原理
Signature Pad 是一个基于 HTML5 Canvas 的轻量级 JavaScript 库,专为创建平滑的电子签名体验而设计。其核心技术灵感源于 Square 公司提出的贝塞尔曲线插值算法,通过动态调整笔迹宽度模拟真实书写压力变化:
// 核心笔迹生成逻辑(简化版)
function _strokeUpdate(event) {
// 计算点与点之间的速度
const velocity = this._calculateCurveSpeed(event);
// 动态调整笔迹宽度(压力敏感效果)
const newWidth = this._calculateStrokeWidth(velocity);
// 使用二次贝塞尔曲线连接点
this._ctx.quadraticCurveTo(
lastPoint.x,
lastPoint.y,
(lastPoint.x + currentPoint.x) / 2,
(lastPoint.y + currentPoint.y) / 2
);
}
📊 贝塞尔曲线插值原理
参数 | 作用 | 默认值 |
---|---|---|
minWidth | 最小线宽(模拟轻压) | 0.5px |
maxWidth | 最大线宽(模拟重压) | 2.5px |
velocityFilterWeight | 速度平滑系数 | 0.7 |
🛠 二、安装与基础使用
安装方式
# NPM 安装
npm install signature_pad
# Yarn 安装
yarn add signature_pad
# CDN 引入
<script src="https://cdn.jsdelivr.net/npm/signature_pad@4.1.7/dist/signature_pad.umd.min.js"></script>
初始化签名板
const canvas = document.getElementById('signature-canvas');
const signaturePad = new SignaturePad(canvas, {
penColor: "rgb(0, 0, 255)", // 蓝色笔迹
backgroundColor: "rgba(255, 255, 255, 0.5)", // 半透明白色背景
minWidth: 1.0,
maxWidth: 4.0,
throttle: 8 // 降低采样频率提升性能
});
⚙️ 三、核心 API 深度解析
1. 数据导出方法
// 获取 PNG 格式的 Base64 数据
const pngData = signaturePad.toDataURL();
// 获取 SVG 原始字符串(保留矢量特性)
const svgString = signaturePad.toSVG({
includeBackgroundColor: true // 包含背景色
});
// 获取原始点数据(适合实时同步)
const pointGroups = signaturePad.toData();
2. 数据导入方法
// 从 PNG 导入签名(会重置画布)
signaturePad.fromDataURL('data:image/png;base64,iVBORw0K...');
// 从原始点数据恢复签名(支持增量绘制)
signaturePad.fromData(pointGroups, { clear: false });
3. 画布控制
// 清空画布并重置状态
signaturePad.clear();
// 检测签名状态
if(signaturePad.isEmpty()) {
alert('请先签署您的名字!');
}
📱 四、高DPI屏幕适配方案
function resizeCanvas() {
const ratio = Math.max(window.devicePixelRatio || 1, 1);
const canvas = signaturePad.canvas;
// 调整画布物理分辨率
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
// 缩放绘图上下文
canvas.getContext('2d').scale(ratio, ratio);
// 保持签名显示
signaturePad.fromData(signaturePad.toData());
}
// 响应窗口变化
window.addEventListener('resize', resizeCanvas);
🧩 五、实战应用技巧
1. 服务器端数据处理(Node.js示例)
// 解析Base64图片数据
app.post('/save-signature', (req, res) => {
const dataURL = req.body.signature;
const base64Data = dataURL.replace(/^data:image\/\w+;base64,/, "");
fs.writeFile('signature.png', base64Data, 'base64', (err) => {
if(err) return res.status(500).send('保存失败');
res.send('签名保存成功');
});
});
2. 签名图片优化处理
// 使用 trim-canvas 库去除空白边缘
import trimCanvas from 'trim-canvas';
const trimmedCanvas = trimCanvas(signaturePad.canvas);
const optimizedData = trimmedCanvas.toDataURL('image/png');
3. 签名事件监听
// 笔迹开始事件
signaturePad.addEventListener('beginStroke', () => {
console.log('签名开始');
});
// 笔迹更新事件
signaturePad.addEventListener('afterUpdateStroke', () => {
realtimePreview(signaturePad.toData());
});
🔧 六、高级配置选项详解
参数 | 类型 | 说明 |
---|---|---|
dotSize | float/function | 点的半径(支持动态函数:(pressure) => pressure * 2 + 1 ) |
minDistance | integer | 采样最小间距(降低锯齿)默认 5px |
throttle | integer | 节流间隔(毫秒),设为 0 禁用节流 |
canvasContextOptions | object | 透传 CanvasRenderingContext2D 配置(如 { willReadFrequently: true } ) |
🚀 性能优化建议
节流采样优化
// 移动端建议值 signaturePad.throttle = 10; // 毫秒 signaturePad.minDistance = 3; // 像素
内存管理
// 离开页面时释放资源 window.addEventListener('beforeunload', () => { signaturePad.off(); signaturePad.canvas = null; });
分层渲染
<!-- 背景层与签名层分离 --> <div class="canvas-container"> <canvas id="bg-layer"></canvas> <canvas id="signature-layer"></canvas> </div>
💎 总结
Signature Pad 通过三项关键技术解决了电子签名的核心痛点:
- 动态笔迹算法
基于速度敏感的贝塞尔曲线插值,完美还原真实书写笔锋 - 跨平台兼容
纯 Canvas 实现,无外部依赖,支持 iOS/Android/PC 全平台 - 数据灵活性
支持从原始点数据到多种图片格式的完整转换链
🧩 建议
- 高DPI设备:必须结合
devicePixelRatio
做画布缩放 - 数据存储:优先保存矢量格式(SVG)或原始点数据
- 性能敏感场景:调整
throttle
和minDistance
平衡流畅度与精度
🔮 未来演进方向
随着 WebGL 的普及,后续版本可探索:
最新技术动态:社区正在实验 WebAssembly 版本,预计提升复杂签名渲染性能 300% 🚀
💡 提示
生产环境中建议结合 Web Workers 处理签名数据转换,避免主线程阻塞导致交互卡顿