vue实现电子签名
实现电子签名功能
在Vue中实现电子签名功能通常需要借助Canvas API进行绘制,并支持导出签名图片。以下是具体实现方法:
核心代码实现
创建一个名为SignaturePad.vue的组件:
<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="button-group">
<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()
},
methods: {
initCanvas() {
this.canvas = this.$refs.canvas
this.ctx = this.canvas.getContext('2d')
// 设置canvas尺寸与实际显示尺寸一致
const rect = this.canvas.getBoundingClientRect()
this.canvas.width = rect.width
this.canvas.height = rect.height
// 初始化样式
this.ctx.strokeStyle = '#000'
this.ctx.lineWidth = 2
this.ctx.lineCap = 'round'
this.ctx.lineJoin = 'round'
},
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()
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 image = this.canvas.toDataURL('image/png')
this.$emit('save', image)
},
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 {
border: 1px solid #ddd;
position: relative;
}
canvas {
width: 100%;
height: 200px;
background-color: #f9f9f9;
touch-action: none;
}
.button-group {
margin-top: 10px;
display: flex;
gap: 10px;
}
button {
padding: 5px 10px;
cursor: pointer;
}
</style>
使用组件示例
在父组件中使用签名组件:
<template>
<div>
<h3>请在此签名</h3>
<SignaturePad @save="handleSaveSignature" />
<div v-if="signatureImage">
<h4>签名预览:</h4>
<img :src="signatureImage" alt="签名" />
</div>
</div>
</template>
<script>
import SignaturePad from './SignaturePad.vue'
export default {
components: {
SignaturePad
},
data() {
return {
signatureImage: null
}
},
methods: {
handleSaveSignature(image) {
this.signatureImage = image
// 可以在这里将图片发送到服务器
}
}
}
</script>
进阶功能扩展
- 签名验证:添加签名完成后的验证逻辑,确保签名符合要求
- 笔迹样式:提供不同颜色和粗细的笔迹选择
- 背景网格:在签名区域添加辅助网格线
- 时间戳:在保存签名时自动添加时间戳
- 多页签名:支持多页文档的连续签名
移动端适配注意事项
- 确保添加了
touch-action: none样式防止页面滚动干扰 - 处理触摸事件时注意调用
preventDefault() - 考虑不同设备像素比的影响,可能需要调整canvas分辨率
服务器端处理
签名图片通常以Base64格式发送到服务器,后端需要将其转换为文件存储:
// Node.js示例
const fs = require('fs')
const base64Data = req.body.image.replace(/^data:image\/png;base64,/, '')
fs.writeFile('signature.png', base64Data, 'base64', (err) => {
if (err) throw err
console.log('签名已保存')
})
以上实现提供了电子签名的基本功能,可根据实际需求进一步扩展和完善。







