vue实现手写签名
<div class="signature-wrap">
<div class="img-wrap" @click="()=>{
show=true
initCanvas()
}">
<img v-if="absPrevdiv" :src="absPrevdiv" />
<span v-else>点击签名</span>
</div>
<el-dialog title="签名" :visible.sync="show" width="30%" :before-close="handleClose">
<div class="signature-contain" ref="canvasHW">
<div class="signature-main" style="z-index: 3000">
<canvas v-if="!disabled" ref="canvasF" class="signature" @mousedown="mouseDown" @mousemove="mouseMove"
@mouseup="mouseUp"></canvas>
<div v-else class="signature signature-disable"></div>
</div>
</div>
<span slot="footer" class="dialog-footer">
<div class="signature-btns">
<div class="btn " @click="show=false">
<span>取</span><span>消</span>
</div>
<div class="btn " @click="handleOverwrite()">
<span>清</span><span>空</span>
</div>
<div class="btn btn-ok" @click="handleSure()">
<span>确</span><span>定</span>
</div>
</div>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'ESignature',
model: {
event: 'change'
},
data() {
return {
show: false,
points: [],
canvasTxt: null,
stage_info: [],
startX: 0,
startY: 0,
moveY: 0,
moveX: 0,
isDown: false,
strokeStyle: '#000',
lineWidth: 2,
absPrevdiv: ''
}
},
methods: {
handleClose() {
this.show = false
},
imageToCanvas() {
var canvas = this.$refs.canvasF
var img = new Image()
img.src = this.absPrevdiv
img.onload = function () {
var ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0)
}
},
// 初始化Canvas
initCanvas() {
this.$nextTick(() => {
let canvas = this.$refs.canvasF
// 获取画布的高度
canvas.height = this.$refs.canvasHW.offsetHeight - 20
// 获取画布的宽度
canvas.width = this.$refs.canvasHW.offsetWidth - 20
// 创建 context 对象
this.canvasTxt = canvas.getContext('2d')
this.stage_info = canvas.getBoundingClientRect()
if (this.absPrevdiv) {
this.imageToCanvas()
}
})
},
// 鼠标按下事件 - 准备绘画
mouseDown(ev) {
ev = ev || event
ev.preventDefault()
if (ev) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
}
this.startX = obj.x
this.startY = obj.y
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.points.push(obj)
this.isDown = true
}
},
// 鼠标移动事件 - 开始绘画
mouseMove(ev) {
ev = ev || event
ev.preventDefault()
if (this.isDown) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
}
this.moveY = obj.y
this.moveX = obj.x
this.canvasTxt.strokeStyle = this.strokeStyle
this.canvasTxt.lineWidth = this.lineWidth
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.startY = obj.y
this.startX = obj.x
this.points.push(obj)
}
},
// 松开鼠标事件 - 停止绘画
mouseUp(ev) {
ev = ev || event
ev.preventDefault()
if (ev) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
}
this.canvasTxt.beginPath()
this.canvasTxt.moveTo(this.startX, this.startY)
this.canvasTxt.lineTo(obj.x, obj.y)
this.canvasTxt.stroke()
this.canvasTxt.closePath()
this.points.push(obj)
this.points.push({ x: -1, y: -1 })
this.isDown = false
}
},
// 返回
handleGoBack() {
this.handleOverwrite()
this.$emit('on-back')
},
// 重写
handleOverwrite() {
this.canvasTxt.clearRect(0, 0, this.$refs.canvasF.width, this.$refs.canvasF.height)
this.points = []
},
handleSure() {
this.absPrevdiv = this.$refs.canvasF.toDataURL()
this.$emit('change', this.absPrevdiv)
this.show = false
console.log(this.absPrevdiv)
}
}
}
</script>
<style lang="less">
.signature-wrap {
height: 100%;
width: 100%;
// padding: 0 5px
// min-width: 60vw
.img-wrap {
width: 200px;
height: 60px;
background: #f3f3f3;
display: flex;
align-items: center;
align-content: center;
justify-content: center;
img {
width: 100%;
height: 100%;
}
// background: red
}
}
.signature-contain {
width: 100%;
.signature-main {
background: white;
flex-direction: row-reverse;
display: flex;
align-items: stretch;
height: 101%;
overflow: scroll;
}
.signature-title {
font-weight: bold;
font-size: 18px;
display: flex;
padding: 0 20rpx;
flex-direction: column;
justify-content: center;
height: 100vh;
color: #333;
span {
transform: rotate(90deg);
}
}
.signature {
border: 1px solid #ccc;
background: #FFF;
margin: 10px 0;
width: 100%;
height: 200px;
align-self: center; // pointer-events:none
}
.signature-disable {
background: #f3f3f3;
}
}
.signature-btns {
display: flex;
justify-content: space-between;
.btn {
padding: 5px 30px;
font-size: 16px;
border: 1px solid #ccc;
border-radius: 6px;
cursor: pointer;
}
.btn-ok {
color: #fff;
border-color: #1890ff;
background: #1890ff;
}
}
</style>
使用
import ESignature from '@/components/ESignature/index.vue'
<ESignature v-model="auditForm.sigImg" />
components: {
ESignature
}