vue 实现电子签名
实现电子签名的基础方法
使用Vue实现电子签名功能,可以通过HTML5的Canvas元素结合触摸或鼠标事件完成。核心步骤包括初始化画布、监听绘制事件、保存签名数据。
<template>
<div>
<canvas
ref="signaturePad"
@mousedown="startDrawing"
@mousemove="draw"
@mouseup="stopDrawing"
@touchstart="startDrawing"
@touchmove="draw"
@touchend="stopDrawing">
</canvas>
<button @click="clearSignature">清除</button>
<button @click="saveSignature">保存</button>
</div>
</template>
<script>
export default {
data() {
return {
isDrawing: false,
canvas: null,
ctx: null
};
},
mounted() {
this.canvas = this.$refs.signaturePad;
this.ctx = this.canvas.getContext('2d');
this.resizeCanvas();
window.addEventListener('resize', this.resizeCanvas);
},
methods: {
resizeCanvas() {
this.canvas.width = this.canvas.offsetWidth;
this.canvas.height = this.canvas.offsetHeight;
},
startDrawing(e) {
this.isDrawing = true;
const pos = this.getPosition(e);
this.ctx.beginPath();
this.ctx.moveTo(pos.x, pos.y);
},
draw(e) {
if (!this.isDrawing) return;
const pos = this.getPosition(e);
this.ctx.lineTo(pos.x, pos.y);
this.ctx.stroke();
},
stopDrawing() {
this.isDrawing = false;
},
getPosition(e) {
const rect = this.canvas.getBoundingClientRect();
return {
x: (e.clientX || e.touches[0].clientX) - rect.left,
y: (e.clientY || e.touches[0].clientY) - rect.top
};
},
clearSignature() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
saveSignature() {
const dataURL = this.canvas.toDataURL('image/png');
console.log(dataURL); // 可上传至服务器或本地保存
}
}
};
</script>
<style scoped>
canvas {
border: 1px solid #000;
width: 100%;
height: 300px;
background-color: #f8f8f8;
}
</style>
使用第三方库优化体验
对于更专业的签名处理,可使用现成库如signature_pad:
-
安装依赖:

npm install signature_pad -
组件实现:
<template> <div> <canvas ref="signatureCanvas"></canvas> <button @click="clear">清除</button> <button @click="save">保存</button> </div> </template>
export default { data() { return { signaturePad: null }; }, mounted() { const canvas = this.$refs.signatureCanvas; canvas.width = canvas.offsetWidth; canvas.height = canvas.offsetHeight; this.signaturePad = new SignaturePad(canvas); }, methods: { clear() { this.signaturePad.clear(); }, save() { if (this.signaturePad.isEmpty()) { alert('请先签名'); return; } const data = this.signaturePad.toDataURL(); console.log(data); } } };

移动端适配要点
- 防止触摸滚动:在画布上添加
@touchmove.prevent修饰符 - 笔迹平滑:调整
signature_pad的throttle和minWidth参数 - 响应式设计:监听窗口变化自动调整画布尺寸
mounted() {
this.initSignaturePad();
window.addEventListener('resize', this.handleResize);
},
methods: {
initSignaturePad() {
const canvas = this.$refs.signatureCanvas;
this.signaturePad = new SignaturePad(canvas, {
minWidth: 1,
maxWidth: 3,
throttle: 16
});
this.handleResize();
},
handleResize() {
const canvas = this.$refs.signatureCanvas;
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
this.signaturePad.clear(); // 防止缩放导致笔迹变形
}
}
签名数据后端处理
保存的Base64数据可通过以下方式处理:
-
前端转换:将Base64转为Blob对象上传
function dataURLToBlob(dataURL) { const arr = dataURL.split(','); const mime = arr[0].match(/:(.*?);/)[1]; const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while (n--) { u8arr[n] = bstr.charCodeAt(n); } return new Blob([u8arr], { type: mime }); } -
后端验证:检查签名图片的有效性(非空白)
isEmpty() { return this.signaturePad.isEmpty(); }
高级功能扩展
- 笔迹颜色设置:通过
penColor参数调整 - 背景网格:在Canvas底层绘制辅助线
- 压力感应:支持数位板压感(需浏览器支持)
- 时间戳水印:在保存时添加签名时间信息
// 设置笔迹颜色示例
setPenColor(color) {
this.signaturePad.penColor = color;
}
以上方案可根据实际需求组合使用,纯前端实现适合简单场景,结合后端存储则能实现完整电子签名流程。






