<template>
|
<el-dialog
|
title="确认签字"
|
:visible.sync="visible"
|
:width="dialogWidth"
|
:close-on-click-modal="false"
|
custom-class="signature-dialog"
|
append-to-body
|
@close="$emit('close', false)"
|
>
|
<div class="signature-container">
|
<div class="signature-content">
|
<canvas
|
ref="signatureCanvas"
|
:width="canvasWidth"
|
:height="canvasHeight"
|
@mousedown="startDrawing"
|
@mousemove="draw"
|
@mouseup="stopDrawing"
|
@mouseleave="stopDrawing"
|
@touchstart="handleTouchStart"
|
@touchmove="handleTouchMove"
|
@touchend="stopDrawing"
|
></canvas>
|
</div>
|
<div class="signature-footer">
|
<el-button type="default" @click="clearCanvas">重置</el-button>
|
<el-button type="primary" @click="confirmSignature">确认</el-button>
|
</div>
|
</div>
|
</el-dialog>
|
</template>
|
|
<script>
|
export default {
|
name: 'SignatureCanvas',
|
props: {
|
visible: {
|
type: Boolean,
|
default: false
|
}
|
},
|
data() {
|
return {
|
isDrawing: false,
|
context: null,
|
lastX: 0,
|
lastY: 0
|
}
|
},
|
computed: {
|
dialogWidth() {
|
// 获取屏幕宽度的80%
|
return window.innerWidth * 0.8 + 'px'
|
},
|
canvasWidth() {
|
// 获取弹窗宽度的90%
|
return window.innerWidth * 0.8 * 0.9
|
},
|
canvasHeight() {
|
// 设置画布高度为宽度的1/3
|
return this.canvasWidth / 3
|
}
|
},
|
watch: {
|
visible(val) {
|
if (val) {
|
this.$nextTick(() => {
|
this.initCanvas()
|
// 添加窗口大小改变的监听
|
window.addEventListener('resize', this.handleResize)
|
})
|
} else {
|
// 移除监听
|
window.removeEventListener('resize', this.handleResize)
|
}
|
}
|
},
|
methods: {
|
handleResize() {
|
// 窗口大小改变时重新初始化画布
|
this.$nextTick(() => {
|
this.initCanvas()
|
})
|
},
|
initCanvas() {
|
const canvas = this.$refs.signatureCanvas
|
this.context = canvas.getContext('2d')
|
this.context.strokeStyle = 'rgba(4, 156, 154, 1)'
|
this.context.lineWidth = 2
|
this.context.lineCap = 'round'
|
this.context.lineJoin = 'round'
|
|
// 清空画布并绘制虚线边框
|
this.clearCanvas()
|
},
|
|
drawDashedBorder() {
|
const ctx = this.context
|
ctx.setLineDash([5, 5])
|
ctx.strokeStyle = '#dcdfe6'
|
ctx.strokeRect(0, 0, this.canvasWidth, this.canvasHeight)
|
ctx.setLineDash([])
|
ctx.strokeStyle = 'rgba(4, 156, 154, 1)'
|
},
|
|
startDrawing(event) {
|
this.isDrawing = true
|
const rect = this.$refs.signatureCanvas.getBoundingClientRect()
|
this.lastX = event.clientX - rect.left
|
this.lastY = event.clientY - rect.top
|
},
|
|
draw(event) {
|
if (!this.isDrawing) return
|
|
const rect = this.$refs.signatureCanvas.getBoundingClientRect()
|
const x = event.clientX - rect.left
|
const y = event.clientY - rect.top
|
|
this.context.beginPath()
|
this.context.moveTo(this.lastX, this.lastY)
|
this.context.lineTo(x, y)
|
this.context.stroke()
|
|
this.lastX = x
|
this.lastY = y
|
},
|
|
handleTouchStart(event) {
|
event.preventDefault()
|
const touch = event.touches[0]
|
const rect = this.$refs.signatureCanvas.getBoundingClientRect()
|
this.lastX = touch.clientX - rect.left
|
this.lastY = touch.clientY - rect.top
|
this.isDrawing = true
|
},
|
|
handleTouchMove(event) {
|
event.preventDefault()
|
if (!this.isDrawing) return
|
|
const touch = event.touches[0]
|
const rect = this.$refs.signatureCanvas.getBoundingClientRect()
|
const x = touch.clientX - rect.left
|
const y = touch.clientY - rect.top
|
|
this.context.beginPath()
|
this.context.moveTo(this.lastX, this.lastY)
|
this.context.lineTo(x, y)
|
this.context.stroke()
|
|
this.lastX = x
|
this.lastY = y
|
},
|
|
stopDrawing() {
|
this.isDrawing = false
|
},
|
|
clearCanvas() {
|
this.context.clearRect(0, 0, this.canvasWidth, this.canvasHeight)
|
this.drawDashedBorder()
|
},
|
|
confirmSignature() {
|
const canvas = this.$refs.signatureCanvas
|
const ctx = this.context
|
|
// 保存当前画布内容
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
|
|
// 先填充背景色
|
ctx.fillStyle = 'rgba(239, 248, 250, 1)'
|
ctx.fillRect(0, 0, canvas.width, canvas.height)
|
|
// 创建一个临时画布来保存签名内容
|
const tempCanvas = document.createElement('canvas')
|
tempCanvas.width = canvas.width
|
tempCanvas.height = canvas.height
|
const tempCtx = tempCanvas.getContext('2d')
|
tempCtx.putImageData(imageData, 0, 0)
|
|
// 将签名内容绘制到主画布上
|
ctx.drawImage(tempCanvas, 0, 0)
|
|
// 导出图片
|
const signatureImage = canvas.toDataURL('image/png')
|
this.$emit('confirm', signatureImage)
|
}
|
},
|
beforeDestroy() {
|
// 组件销毁前移除监听
|
window.removeEventListener('resize', this.handleResize)
|
}
|
}
|
</script>
|
|
<style lang="less" scoped>
|
.signature-dialog {
|
:deep(.el-dialog__body) {
|
padding: 0;
|
}
|
:deep(.el-dialog) {
|
margin-top: 10vh !important;
|
}
|
}
|
|
.signature-container {
|
background: #fff;
|
border-radius: 4px;
|
|
.signature-content {
|
padding: 20px;
|
display: flex;
|
justify-content: center;
|
|
canvas {
|
border-radius: 4px;
|
background: rgba(239, 248, 250, 1);
|
width: 100%;
|
height: 100%;
|
}
|
}
|
|
.signature-footer {
|
padding: 20px;
|
border-top: 1px solid #dcdfe6;
|
display: flex;
|
justify-content: flex-end;
|
gap: 12px;
|
button{
|
width: 150px;
|
}
|
}
|
}
|
</style>
|