parent
b4a9568fad
commit
beb20c6497
@ -0,0 +1,30 @@ |
||||
import Vue from 'vue' |
||||
import Main from './main.vue' |
||||
|
||||
const Constructor = Vue.extend(Main) |
||||
|
||||
let instance |
||||
|
||||
const signature = function ({image, lineWidth = 6, lineColor = '#000000', onConfirm}) { |
||||
if (instance) instance.close() |
||||
else { |
||||
instance = new Constructor().$mount() |
||||
document.body.appendChild(instance.$el) |
||||
} |
||||
instance.image = image |
||||
instance.lineWidth = lineWidth |
||||
instance.lineColor = lineColor |
||||
instance.onConfirm = onConfirm |
||||
instance.init() |
||||
instance.visible = true |
||||
return instance |
||||
} |
||||
|
||||
signature.close = function () { |
||||
if (instance) { |
||||
instance.close() |
||||
instance = null |
||||
} |
||||
} |
||||
|
||||
export default signature |
||||
@ -0,0 +1,155 @@ |
||||
<template> |
||||
<div v-show="visible" class="signature-board"> |
||||
<canvas |
||||
ref="canvas" |
||||
@mousedown.prevent="drawStart" |
||||
@mousemove.prevent="drawMove" |
||||
@mouseup.prevent="drawEnd" |
||||
@touchstart.prevent="drawStart" |
||||
@touchmove.prevent="drawMove" |
||||
@touchend.prevent="drawEnd" |
||||
/> |
||||
<div class="signature-board__footer"> |
||||
<el-button plain size="small" @click="clear">清 空</el-button> |
||||
<el-button plain size="small" @click="close">关 闭</el-button> |
||||
<el-button size="small" type="primary" @click="confirm">确 定</el-button> |
||||
</div> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
/* |
||||
* 突然发现没办法做到竖屏横屏都支持,坑爹 |
||||
* */ |
||||
|
||||
function getEventPoint(e) { |
||||
let x, y |
||||
if (['mousedown', 'mousemove'].includes(e.type)) { |
||||
x = e.clientX - e.target.offsetLeft |
||||
y = e.clientY - e.target.offsetTop |
||||
} |
||||
else { |
||||
x = e.changedTouches[0].clientX - e.target.offsetLeft |
||||
y = e.changedTouches[0].clientY - e.target.offsetTop |
||||
} |
||||
return {x, y} |
||||
} |
||||
|
||||
export default { |
||||
name: 'SignatureBoard', |
||||
props: { |
||||
image: String, |
||||
lineWidth: Number, |
||||
lineColor: String, |
||||
onConfirm: Function |
||||
}, |
||||
data() { |
||||
return { |
||||
visible: false, |
||||
drew: false, |
||||
drawing: false, |
||||
startX: 0, |
||||
startY: 0 |
||||
} |
||||
}, |
||||
methods: { |
||||
drawStart(e) { |
||||
const {x, y} = getEventPoint(e) |
||||
this.drew = true |
||||
this.drawing = true |
||||
this.startX = x |
||||
this.startY = y |
||||
this.ctx.strokeStyle = this.lineColor |
||||
this.ctx.lineWidth = this.lineWidth |
||||
}, |
||||
|
||||
drawMove(e) { |
||||
if (!this.drawing) return |
||||
const {x, y} = getEventPoint(e) |
||||
this.ctx.beginPath() |
||||
this.ctx.moveTo(this.startX, this.startY) |
||||
this.ctx.lineTo(x, y) |
||||
this.ctx.stroke() |
||||
this.ctx.closePath() |
||||
this.startY = y |
||||
this.startX = x |
||||
}, |
||||
|
||||
drawEnd() { |
||||
this.drawing = false |
||||
}, |
||||
|
||||
getBase64() { |
||||
if (!this.drew) return null |
||||
return this.$refs.canvas.toDataURL() |
||||
}, |
||||
|
||||
resize() { |
||||
const canvas = this.$refs.canvas |
||||
|
||||
canvas.height = window.innerHeight |
||||
canvas.width = window.innerWidth |
||||
}, |
||||
|
||||
init() { |
||||
this.resize() |
||||
|
||||
this.ctx = this.$refs.canvas.getContext('2d') |
||||
this.ctx.lineCap = 'round' |
||||
this.ctx.lineJoin = 'round' |
||||
|
||||
if (this.image) { |
||||
let img = new Image() |
||||
img.src = this.image |
||||
img.onload = () => { |
||||
this.ctx.drawImage(img, 0, 0, img.width, img.height) |
||||
this.drew = true |
||||
img = null |
||||
} |
||||
} |
||||
}, |
||||
|
||||
clear() { |
||||
this.drew = false |
||||
this.drawing = false |
||||
this.$refs.canvas && (this.$refs.canvas.height = window.innerHeight) |
||||
}, |
||||
|
||||
close() { |
||||
this.visible = false |
||||
this.clear() |
||||
}, |
||||
|
||||
confirm() { |
||||
this.onConfirm && this.onConfirm(this.getBase64()) |
||||
this.visible = false |
||||
} |
||||
}, |
||||
mounted() { |
||||
window.addEventListener('resize', this.resize) |
||||
}, |
||||
destroyed() { |
||||
this.clear() |
||||
window.removeEventListener('resize', this.resize) |
||||
} |
||||
} |
||||
</script> |
||||
|
||||
<style lang="scss"> |
||||
.signature-board { |
||||
position: fixed; |
||||
background-color: white; |
||||
top: 0; |
||||
right: 0; |
||||
height: 100vh; |
||||
width: 100vw; |
||||
z-index: 100; |
||||
overflow: hidden; |
||||
|
||||
&__footer { |
||||
position: absolute; |
||||
bottom: 20px; |
||||
right: 20px; |
||||
} |
||||
} |
||||
</style> |
||||
@ -0,0 +1,29 @@ |
||||
<template> |
||||
<div> |
||||
<div class="tip-row"> |
||||
搞了个手写签名,竖屏横屏不可兼得 |
||||
</div> |
||||
<div> |
||||
<img :src="src" style="width: 100%;height: 500px;object-fit: contain"> |
||||
</div> |
||||
<el-button plain @click="signature">点击签名</el-button> |
||||
</div> |
||||
</template> |
||||
|
||||
<script> |
||||
export default { |
||||
name: 'signatureExample', |
||||
data() { |
||||
return { |
||||
src: null |
||||
} |
||||
}, |
||||
methods: { |
||||
signature() { |
||||
this.$signature({ |
||||
image: this.src, onConfirm: img => this.src = img |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
</script> |
||||
Loading…
Reference in new issue