如何用HTML5 Canvas实现电子签名功能✍️
🤖 作者简介:水煮白菜王,一位资深前端劝退师 👻
👀 文章专栏: 前端专栏 ,记录一下平时在博客写作中,总结出的一些开发技巧和知识归纳总结✍。
感谢支持💕💕💕
🖌️电子签名作为数字化转型的重要环节,在前端领域可通过HTML5 Canvas轻松实现。本文将以HTML Demo示例🎨,手把手带您完成一个电子签名功能。
目录
- 一、实现原理与核心技术
- 二、核心代码实现解析
- 2.1 画布初始化
- 2.2 画笔样式配置
- 2.3 设备兼容处理
- 2.4 绘制逻辑实现
- 起笔监听:
- 移动绘制:
- 收笔处理:
- 2.5 功能按钮实现
- 清空画布:
- 保存签名:
- 可加撤销功能:
- 三、注意事项
- 四、完整代码Demo示例
- 五、总结
一、实现原理与核心技术
通过HTML5 Canvas的2D绘图上下文实现轨迹捕捉,结合事件监听处理完成核心绘制功能。关键技术点包括:
- Canvas绘图API:Path路径操作
- 事件系统:鼠标/触摸事件统一处理
- 文件导出:Canvas转Blob对象
二、核心代码实现解析
2.1 画布初始化
设置600x300画布并获取2D上下文,建议根据屏幕尺寸动态调整画布大小。
const canvas = document.querySelector('canvas');
canvas.width = 500;
canvas.height = 300;
const ctx = canvas.getContext('2d');
2.2 画笔样式配置
通过lineCap和lineJoin实现自然的手写效果。
ctx.lineWidth = 3;
ctx.strokeStyle = 'red';
ctx.lineCap = 'round'; // 圆角线头
ctx.lineJoin = 'round'; // 圆角连接
2.3 设备兼容处理
通过UA检测自动切换触摸/鼠标事件,实际项目中建议使用pointer events实现更优雅的兼容。
const mobileStatus = /Mobile|Android|iPhone/i.test(navigator.userAgent);
2.4 绘制逻辑实现
起笔监听:
function start(event) {
const pos = mobileStatus ? event.changedTouches[0] : event;
ctx.beginPath();
ctx.moveTo(pos.pageX, pos.pageY);
window.addEventListener(mobileStatus ? 'touchmove' : 'mousemove', draw);
}
移动绘制:
function draw(event) {
const pos = mobileStatus ? event.changedTouches[0] : event;
ctx.lineTo(pos.pageX, pos.pageY);
ctx.stroke(); // 实时渲染路径
}
收笔处理:
function closeDraw() {
window.removeEventListener('mousemove', draw);
}
2.5 功能按钮实现
清空画布:
function cancel() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
保存签名:
function save() {
canvas.toBlob(blob => {
const a = document.createElement('a');
a.download = `${Date.now()}.png`;
a.href = URL.createObjectURL(blob);
a.click();
});
}
可加撤销功能:
let history = [];
// 绘制时保存状态
history.push(ctx.getImageData(0,0,canvas.width,canvas.height));
function undo() {
if(history.length > 1) {
history.pop();
ctx.putImageData(history[history.length-1], 0,0);
}
}
三、注意事项
- 性能优化:大数据量绘制建议使用requestAnimationFrame
- 跨域问题:若涉及图片合成需设置crossOrigin=“anonymous”
- 移动端适配:添加CSS样式防止触摸滚动
canvas {
touch-action: none;
background: #f8f8f8;
}
四、完整代码Demo示例
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
* {
margin: 0 auto;
padding: 0;
}
button {
padding: 3px 5px;
margin: 5px;
}
</style>
</head>
<body>
<canvas id="sign"></canvas>
<div>
<button onclick="cancel()">取消</button>
<button onclick="save()">保存</button>
</div>
</body>
<script>
const canvas = document.querySelector('canvas');
canvas.width = 600;
canvas.height = 300;
canvas.style.borderRadius = '5px';
canvas.style.border = '1px solid #a6a9ad';
const ctx = canvas.getContext('2d');
// 高清屏适配
const scale = window.devicePixelRatio;
canvas.width = 600 * scale;
canvas.height = 300 * scale;
ctx.scale(scale, scale);
ctx.lineWidth = 3; //线宽
ctx.strokeStyle = 'black'; //线颜色
ctx.lineCap = 'round'; //线条的结束端点样式
ctx.lineJoin = 'round'; //两条线相交时,所创建的拐角类型
// 检测移动设备
const mobileStatus = /Mobile|Android|iPhone/i.test(navigator.userAgent);
const start = (event) => {
const { offsetX, offsetY, pageX, pageY } = mobileStatus
? event.changedTouches[0]
: event;
ctx.beginPath(); //起始一条路径,或重置当前路径
ctx.moveTo(pageX, pageY); //把路径移动到画布中的指定点,不创建线条
window.addEventListener(mobileStatus ? 'touchmove' : 'mousemove', draw);
};
const draw = (event) => {
const { pageX, pageY } = mobileStatus ? event.changedTouches[0] : event;
ctx.lineTo(pageX, pageY); //添加一个新点,然后在画布中创建从该点到最后指定点的线条
ctx.stroke(); //绘制已定义的路径
};
const cloaseDraw = () => {
window.removeEventListener('mousemove', draw);
};
window.addEventListener(mobileStatus ? 'touchstart' : 'mousedown', start);
window.addEventListener(mobileStatus ? 'touchend' : 'mouseup', cloaseDraw);
const cancel = () => {
ctx.clearRect(0, 0, 600, 300); //在给定的矩形内清除指定的像素
};
const save = () => {
canvas.toBlob((blob) => {
const date = Date.now().toString();
const a = document.createElement('a');
a.download = `${date}.png`;
a.href = URL.createObjectURL(blob);
a.click();
a.remove();
});
};
</script>
</html>
五、总结
本文实现的电子签名方案具备以下特点:
- 支持移动端与PC端双平台
- 输出为PNG透明图片
- 代码精简
- 无第三方依赖
实际项目中需结合后端实现签名验证、添加时间戳等扩展功能。可继续丰富代码逻辑:
- 添加Base64导出功能
- 实现笔锋效果(通过速度计算线宽)
- 添加本地存储自动保存
Canvas的绘图能力还能延伸应用于手写笔记、电子批注等场景。
如果你觉得这篇文章对你有帮助,请点赞 👍、收藏 👏 并关注我!👀