使用sign-canvas完成电子签名后需要加上签名的预览功能有什么比较好的实现思路吗
this.$refs.SignCanvas.saveAsImg()
看文档这个方法返回了图片base64路径,写个弹框用img显示。
实现签名预览需要一些基本的实现思路,下面是我为您提供的一些思路:
获取签名图片数据
首先,使用 sign-canvas 完成签名后,需要从该工具中获取签名后的图片数据。可以通过将签名图片保存到服务器端,将其转换成 Base64 字符串或使用其他方式将其发送到客户端。
显示签名图片
一旦获取到签名图片数据,客户端就可以使用 HTML Canvas 对象加载并显示基于该签名数据的图像。可以通过以下方式实现:
创建一个空的
操作签名图片
如果您需要数据,比如签名日期或签字人姓名这样的附加信息,可以在签名时一并提交。可以将这些附加信息存储在本地或服务器上,以便在签名预览中使用。您也可以在签名预览中提供一些工具,比如调整签名笔画的颜色和粗细等。
以上是签名预览的一些实现思路,您也可以按照这个流程进行实现,并结合您的实际需求,添加更多的功能。希望这可以帮助您。
<template>
<div class="sign-canvas">
<van-overlay :show="show" @click="hideCanvas">
<div class="wrapper" @click.stop>
<div ref="canvasHw" class="overlay-content">
<div class="overlay-title">请签名</div>
<canvas
ref="canvas"
canvas-id="signCanvas"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="mouseUp"/>
<div class="contents-buttons">
<div v-show="isCheat !== 1" class="contents-button" @click="cancleSign">取消</div>
<div v-show="isCheat !== 1" class="contents-button" @click="clearCanvas">清除</div>
<div class="contents-button" @click="saveCanvas">确定</div>
</div>
</div>
</div>
</van-overlay>
</div>
</template>
<script>
var canvas = null
var canvasTxt = null
var points = []
export default {
name: 'SignCanvas',
props: {
show: {
type: Boolean,
default: false
},
isCheat: {
type: Number,
default: 0
}
},
data() {
return {
client: {},
startX: 0,
startY: 0,
moveY: 0,
moveX: 0,
isDown: false
}
},
mounted() {
this.initCanvas()
},
methods: {
hideCanvas() {
if (this.isCheat === 1) {
return
} else {
this.show = false
}
},
initCanvas() {
canvas = this.$refs.canvas// 指定canvas
canvas.width = window.screen.availWidth - 80
canvas.height = 300
canvasTxt = canvas.getContext('2d')// 设置2D渲染区域
canvasTxt.lineWidth = 3 // 设置线的宽度
canvasTxt.lineCap = 'round'
canvasTxt.lineJoin = 'round'
},
// mobile
touchStart(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length === 1) {
const obj = {
x: ev.touches[0].pageX - canvas.offsetLeft,
y: ev.touches[0].pageY - canvas.offsetTop
}
this.startX = obj.x
this.startY = obj.y
canvasTxt.beginPath()
canvasTxt.moveTo(this.startX, this.startY)
canvasTxt.lineTo(obj.x, obj.y)
canvasTxt.closePath()
canvasTxt.stroke()
points.push(obj)
}
},
touchMove(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length === 1) {
const obj = {
x: ev.touches[0].pageX - canvas.offsetLeft,
y: ev.touches[0].pageY - canvas.offsetTop
}
canvasTxt.beginPath()
canvasTxt.moveTo(this.startX, this.startY)
canvasTxt.lineTo(obj.x, obj.y)
canvasTxt.stroke()
canvasTxt.closePath()
this.startX = obj.x
this.startY = obj.y
points.push(obj)
}
},
touchEnd(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length === 1) {
const obj = {
x: ev.touches[0].pageX - canvas.offsetLeft,
y: ev.touches[0].pageY - canvas.offsetTop
}
canvasTxt.beginPath()
canvasTxt.moveTo(this.startX, this.startY)
canvasTxt.lineTo(obj.x, obj.y)
canvasTxt.stroke()
canvasTxt.closePath()
points.push(obj)
}
},
// pc
mouseDown(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length === 1) {
const obj = {
x: ev.touches[0].pageX - canvas.offsetLeft,
y: ev.touches[0].pageY - canvas.offsetTop
}
this.startX = obj.x
this.startY = obj.y
canvasTxt.beginPath()
canvasTxt.moveTo(this.startX, this.startY)
canvasTxt.lineTo(obj.x, obj.y)
canvasTxt.stroke()
canvasTxt.closePath()
points.push(obj)
this.isDown = true
}
},
mouseMove(ev) {
ev = ev || event
ev.preventDefault()
if (this.isDown) {
const obj = {
x: ev.touches[0].pageX - canvas.offsetLeft,
y: ev.touches[0].pageY - canvas.offsetTop
}
canvasTxt.beginPath()
canvasTxt.moveTo(this.startX, this.startY)
canvasTxt.lineTo(obj.x, obj.y)
canvasTxt.stroke()
canvasTxt.closePath()
this.startY = obj.y
this.startX = obj.x
points.push(obj)
}
},
mouseUp(ev) {
ev = ev || event
ev.preventDefault()
if (ev.touches.length === 1) {
const obj = {
x: ev.touches[0].pageX - canvas.offsetLeft,
y: ev.touches[0].pageY - canvas.offsetTop
}
canvasTxt.beginPath()
canvasTxt.moveTo(this.startX, this.startY)
canvasTxt.lineTo(obj.x, obj.y)
canvasTxt.stroke()
canvasTxt.closePath()
points.push(obj)
points.push({ x: -1, y: -1 })
this.isDown = false
}
},
cancleSign() {
this.clearCanvas()
this.$emit('cancle')
},
// 重写
clearCanvas() {
canvasTxt.clearRect(0, 0, this.$refs.canvas.width, this.$refs.canvas.height)
points = []
this.$emit('clear')
},
// 确定签名
async saveCanvas() {
const file = {}
file.type = 'image/png'
file.name = 'sign.png'
file.content = this.$refs.canvas.toDataURL()
const imgFile = await this.dataURLToBlob(file)
this.$emit('save', imgFile)
},
dataURLToBlob(file) {
var arr = file.content.split(',')
const bstr = atob(arr[1])
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], file.name, {
type: file.type
})
}
}
}
</script>
<style scoped lang="scss">
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
padding: 0 40px;
}
.overlay-content {
border: 1px solid #ededed;
background-color: white;
border-radius: 20px;
width: 100%;
.contents-signCanvas {
width: 100%;
height: 200px;
}
.overlay-title {
text-align: center;
font-size: 16px;
padding: 10px 0;
font-weight: bold;
border-bottom: 1px solid #ededed;
}
.contents-buttons {
display: flex;
justify-content: space-between;
padding: 5px 0;
border-top: 1px solid #ededed;
.contents-button {
padding: 10px 0;
text-align: center;
flex: 1;
font-size: 15px;
color: rgba(37, 127, 255, 1);
}
}
}
</style>