vue 实现电子签名
实现电子签名的基本思路
在Vue中实现电子签名功能,主要涉及以下几个关键点:使用HTML5 Canvas绘制签名、保存签名数据、清除签名以及响应式调整画布大小。
安装依赖(可选)
如果项目需要更复杂的签名处理,可以安装signature_pad库:
npm install signature_pad
基础实现代码示例
<template>
<div class="signature-container">
<canvas
ref="canvas"
@mousedown="startDrawing"
@mousemove="draw"
@mouseup="stopDrawing"
@mouseleave="stopDrawing"
@touchstart="handleTouchStart"
@touchmove="handleTouchMove"
@touchend="handleTouchEnd"
></canvas>
<div class="controls">
<button @click="clearSignature">清除</button>
<button @click="saveSignature">保存</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
isDrawing: false,
lastX: 0,
lastY: 0,
canvas: null,
ctx: null
}
},
mounted() {
this.initCanvas()
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
},
methods: {
initCanvas() {
this.canvas = this.$refs.canvas
this.ctx = this.canvas.getContext('2d')
this.resizeCanvas()
// 设置绘制样式
this.ctx.strokeStyle = '#000'
this.ctx.lineWidth = 2
this.ctx.lineCap = 'round'
this.ctx.lineJoin = 'round'
},
resizeCanvas() {
const parent = this.canvas.parentElement
this.canvas.width = parent.offsetWidth
this.canvas.height = parent.offsetHeight * 0.8
},
handleResize() {
this.resizeCanvas()
},
startDrawing(e) {
this.isDrawing = true
const pos = this.getPosition(e)
this.lastX = pos.x
this.lastY = pos.y
},
draw(e) {
if (!this.isDrawing) return
const pos = this.getPosition(e)
this.ctx.beginPath()
this.ctx.moveTo(this.lastX, this.lastY)
this.ctx.lineTo(pos.x, pos.y)
this.ctx.stroke()
this.lastX = pos.x
this.lastY = pos.y
},
stopDrawing() {
this.isDrawing = false
},
getPosition(e) {
const rect = this.canvas.getBoundingClientRect()
let x, y
if (e.type.includes('touch')) {
x = e.touches[0].clientX - rect.left
y = e.touches[0].clientY - rect.top
} else {
x = e.clientX - rect.left
y = e.clientY - rect.top
}
return { x, y }
},
clearSignature() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
},
saveSignature() {
const dataURL = this.canvas.toDataURL('image/png')
// 可以发送到服务器或保存到本地
console.log(dataURL)
this.$emit('signature-saved', dataURL)
},
handleTouchStart(e) {
e.preventDefault()
this.startDrawing(e)
},
handleTouchMove(e) {
e.preventDefault()
this.draw(e)
},
handleTouchEnd(e) {
e.preventDefault()
this.stopDrawing()
}
}
}
</script>
<style scoped>
.signature-container {
width: 100%;
height: 100%;
}
canvas {
border: 1px solid #ddd;
background-color: white;
}
.controls {
margin-top: 10px;
}
button {
margin-right: 10px;
}
</style>
使用signature_pad库的优化方案
<template>
<div>
<canvas ref="canvas"></canvas>
<button @click="clear">清除</button>
<button @click="save">保存</button>
</div>
</template>
<script>
import SignaturePad from 'signature_pad'
export default {
data() {
return {
signaturePad: null
}
},
mounted() {
this.signaturePad = new SignaturePad(this.$refs.canvas, {
minWidth: 1,
maxWidth: 3,
penColor: 'black'
})
this.resizeCanvas()
window.addEventListener('resize', this.resizeCanvas)
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeCanvas)
},
methods: {
resizeCanvas() {
const canvas = this.$refs.canvas
const ratio = Math.max(window.devicePixelRatio || 1, 1)
canvas.width = canvas.offsetWidth * ratio
canvas.height = canvas.offsetHeight * ratio
canvas.getContext('2d').scale(ratio, ratio)
this.signaturePad.clear() // 防止缩放后签名模糊
},
clear() {
this.signaturePad.clear()
},
save() {
if (this.signaturePad.isEmpty()) {
alert('请先签名')
return
}
const data = this.signaturePad.toDataURL()
this.$emit('save', data)
}
}
}
</script>
实现要点说明
画布初始化 确保画布大小适应容器,并设置好绘制样式。对于高DPI屏幕,需要考虑像素比例。

触摸支持 通过添加触摸事件处理程序,使签名功能在移动设备上也能正常工作。
数据保存 使用Canvas的toDataURL方法将签名转换为Base64格式的图片数据,便于存储或上传。

响应式处理 监听窗口大小变化事件,动态调整画布尺寸,保证签名区域始终适合当前视图。
样式优化 添加适当的边框和背景色,使签名区域清晰可见。控制按钮提供基本的交互功能。
进阶功能建议
- 添加签名验证功能,检测签名是否为空
- 实现撤销上一步操作的功能
- 支持多种笔触颜色和粗细选择
- 添加时间戳等元数据到签名图片
- 集成后端API实现签名存储和验证






