电子签名
This commit is contained in:
parent
6ca132970b
commit
31ccf971d9
|
|
@ -68,13 +68,17 @@ if (memberStore.userInfo.nickName && memberStore.userInfo.nickName.length < 5) {
|
||||||
nickName.value = '正楷字书写'
|
nickName.value = '正楷字书写'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const paths = ref([]) // 保存所有笔迹(每笔是一组点数组)
|
||||||
|
const PEN = { width: 6, color: '#000000' } // 若你已有类似配置可复用
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.modelValue,
|
() => props.modelValue,
|
||||||
(val) => {
|
(val) => {
|
||||||
if (val) {
|
if (val) {
|
||||||
// 小延时确保 canvas 已经渲染
|
// 小延时确保 canvas 已经渲染
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
uni.createSelectorQuery()
|
uni
|
||||||
|
.createSelectorQuery()
|
||||||
.in(_this)
|
.in(_this)
|
||||||
.select('#mycanvas')
|
.select('#mycanvas')
|
||||||
.fields({ size: true, rect: true }, (data) => {
|
.fields({ size: true, rect: true }, (data) => {
|
||||||
|
|
@ -86,7 +90,7 @@ watch(
|
||||||
.exec()
|
.exec()
|
||||||
}, 50) // 可以尝试 30~100ms,根据实际机型调整
|
}, 50) // 可以尝试 30~100ms,根据实际机型调整
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
const showRotateToast = (msg) => {
|
const showRotateToast = (msg) => {
|
||||||
|
|
@ -143,43 +147,62 @@ const drawBackground = (ctx, width = 100, height = 100) => {
|
||||||
|
|
||||||
// 触摸开始
|
// 触摸开始
|
||||||
const touchstart = (e) => {
|
const touchstart = (e) => {
|
||||||
let startX = e.changedTouches[0].x
|
const x = e.changedTouches[0].x
|
||||||
let startY = e.changedTouches[0].y
|
const y = e.changedTouches[0].y
|
||||||
let startPoint = { X: startX, Y: startY }
|
const p = { X: x, Y: y }
|
||||||
points.push(startPoint)
|
|
||||||
|
// 新开一条路径并保存第一个点
|
||||||
|
paths.value.push([p])
|
||||||
|
|
||||||
|
// 立即在可见画布上开始一段(方便用户看到)
|
||||||
|
canvaCtx.setLineWidth(PEN.width)
|
||||||
|
canvaCtx.setStrokeStyle(PEN.color)
|
||||||
|
canvaCtx.setLineCap('round')
|
||||||
|
canvaCtx.setLineJoin('round')
|
||||||
|
|
||||||
canvaCtx.beginPath()
|
canvaCtx.beginPath()
|
||||||
}
|
canvaCtx.moveTo(x, y)
|
||||||
// 触摸移动
|
// 画一个极短的线段以显示起点(某些设备单点才会丢失)
|
||||||
const touchmove = (e) => {
|
canvaCtx.lineTo(x + 0.1, y + 0.1)
|
||||||
let moveX = e.changedTouches[0].x
|
|
||||||
let moveY = e.changedTouches[0].y
|
|
||||||
let movePoint = { X: moveX, Y: moveY }
|
|
||||||
points.push(movePoint)
|
|
||||||
if (points.length >= 2) {
|
|
||||||
draw()
|
|
||||||
hasDrawn.value = true // 标记已签名
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 绘制
|
|
||||||
const draw = () => {
|
|
||||||
if (points.length < 2) return
|
|
||||||
canvaCtx.beginPath()
|
|
||||||
canvaCtx.moveTo(points[0].X, points[0].Y)
|
|
||||||
for (let i = 1; i < points.length; i++) {
|
|
||||||
canvaCtx.lineTo(points[i].X, points[i].Y)
|
|
||||||
}
|
|
||||||
canvaCtx.stroke()
|
canvaCtx.stroke()
|
||||||
canvaCtx.draw(true)
|
canvaCtx.draw(true)
|
||||||
points = [points[points.length - 1]]
|
|
||||||
}
|
}
|
||||||
// 触摸结束
|
|
||||||
|
const touchmove = (e) => {
|
||||||
|
const x = e.changedTouches[0].x
|
||||||
|
const y = e.changedTouches[0].y
|
||||||
|
const p = { X: x, Y: y }
|
||||||
|
|
||||||
|
// 把点推入当前路径
|
||||||
|
const cur = paths.value[paths.value.length - 1]
|
||||||
|
if (cur) cur.push(p)
|
||||||
|
|
||||||
|
// 在可见画布上增量画这段
|
||||||
|
canvaCtx.setLineWidth(PEN.width)
|
||||||
|
canvaCtx.setStrokeStyle(PEN.color)
|
||||||
|
canvaCtx.setLineCap('round')
|
||||||
|
canvaCtx.setLineJoin('round')
|
||||||
|
|
||||||
|
if (cur && cur.length >= 2) {
|
||||||
|
const prev = cur[cur.length - 2]
|
||||||
|
canvaCtx.beginPath()
|
||||||
|
canvaCtx.moveTo(prev.X, prev.Y)
|
||||||
|
canvaCtx.lineTo(p.X, p.Y)
|
||||||
|
canvaCtx.stroke()
|
||||||
|
canvaCtx.draw(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const touchend = () => {
|
const touchend = () => {
|
||||||
|
// 不清 paths,保留以便导出;清掉临时 points(如果你还用 points)
|
||||||
points = []
|
points = []
|
||||||
|
hasDrawn.value = paths.value.length > 0
|
||||||
}
|
}
|
||||||
// 清空画布
|
// 清空画布
|
||||||
const clear = () => {
|
const clear = () => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
uni.createSelectorQuery()
|
uni
|
||||||
|
.createSelectorQuery()
|
||||||
.in(_this)
|
.in(_this)
|
||||||
.select('#mycanvas')
|
.select('#mycanvas')
|
||||||
.fields({ size: true, rect: true }, (data) => {
|
.fields({ size: true, rect: true }, (data) => {
|
||||||
|
|
@ -188,9 +211,14 @@ const clear = () => {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const { width, height } = data
|
const { width, height } = data
|
||||||
|
// 清空像素
|
||||||
canvaCtx.clearRect(0, 0, width, height)
|
canvaCtx.clearRect(0, 0, width, height)
|
||||||
|
// flush 清空,再画背景(drawBackground 会 ctx.draw)
|
||||||
canvaCtx.draw(false, () => {
|
canvaCtx.draw(false, () => {
|
||||||
drawBackground(canvaCtx, width, height) // ⚡ 保证背景立即重绘
|
// 重绘背景(你的 drawBackground 会自己 ctx.draw)
|
||||||
|
drawBackground(canvaCtx, width, height)
|
||||||
|
// 清空笔迹记录
|
||||||
|
paths.value = []
|
||||||
hasDrawn.value = false
|
hasDrawn.value = false
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
|
|
@ -205,11 +233,73 @@ const confirm = () => {
|
||||||
showRotateToast('请先签名再确认')
|
showRotateToast('请先签名再确认')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
uni.canvasToTempFilePath({ canvasId: 'mycanvas' }, _this, _this.parent).then((res) => {
|
|
||||||
|
uni
|
||||||
|
.createSelectorQuery()
|
||||||
|
.in(_this)
|
||||||
|
.select('#mycanvas')
|
||||||
|
.fields({ size: true, rect: true }, (data) => {
|
||||||
|
if (!data) return
|
||||||
|
const { width, height } = data
|
||||||
|
|
||||||
|
// 1) 清空整个画布(包括背景)
|
||||||
|
canvaCtx.clearRect(0, 0, width, height)
|
||||||
|
|
||||||
|
// 2) 在画布上只重绘笔迹(不画背景)
|
||||||
|
canvaCtx.setLineWidth(PEN.width)
|
||||||
|
canvaCtx.setStrokeStyle(PEN.color)
|
||||||
|
canvaCtx.setLineCap('round')
|
||||||
|
canvaCtx.setLineJoin('round')
|
||||||
|
canvaCtx.setFillStyle(PEN.color)
|
||||||
|
|
||||||
|
paths.value.forEach((path) => {
|
||||||
|
if (!path || !path.length) return
|
||||||
|
if (path.length === 1) {
|
||||||
|
// 单点:画小圆点
|
||||||
|
const p = path[0]
|
||||||
|
canvaCtx.beginPath()
|
||||||
|
canvaCtx.arc(p.X, p.Y, Math.max(1, PEN.width / 2), 0, Math.PI * 2)
|
||||||
|
canvaCtx.fill()
|
||||||
|
} else {
|
||||||
|
canvaCtx.beginPath()
|
||||||
|
canvaCtx.moveTo(path[0].X, path[0].Y)
|
||||||
|
for (let i = 1; i < path.length; i++) {
|
||||||
|
canvaCtx.lineTo(path[i].X, path[i].Y)
|
||||||
|
}
|
||||||
|
canvaCtx.stroke()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// 3) flush 并在回调中导出(确保像素已写入)
|
||||||
|
canvaCtx.draw(false, () => {
|
||||||
|
uni
|
||||||
|
.canvasToTempFilePath(
|
||||||
|
{
|
||||||
|
canvasId: 'mycanvas',
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
destWidth: width,
|
||||||
|
destHeight: height,
|
||||||
|
fileType: 'png',
|
||||||
|
quality: 1,
|
||||||
|
},
|
||||||
|
_this,
|
||||||
|
_this.parent,
|
||||||
|
)
|
||||||
|
.then((res) => {
|
||||||
emits('complete', res.tempFilePath)
|
emits('complete', res.tempFilePath)
|
||||||
|
// 直接关闭(按你要求:不再恢复背景)
|
||||||
cancel()
|
cancel()
|
||||||
})
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error('导出签名失败', err)
|
||||||
|
showRotateToast('导出失败,请重试')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.exec()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消
|
// 取消
|
||||||
const cancel = () => {
|
const cancel = () => {
|
||||||
clear().then(() => emits('update:modelValue', false))
|
clear().then(() => emits('update:modelValue', false))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue