代码如下:
HTML:
<div> <canvas @touchstart="touchStart($event)" @touchmove="touchMove($event)" @touchend="touchEnd($event)" ref="canvasF"></canvas> <div class="u-p-l-24"> <van-button color="#FF970C" size="normal" round plain class="u-m-r-16 signBtn" @click="overwrite">重签</van-button> <van-button color="#FF970C" size="normal" round class="signBtn" @click="seaveImages">完成签名</van-button> </div> </div>
JS:
let canvasClientWidth = ref(document.documentElement.clientWidth)
let canvasClientHeight = ref(document.documentElement.clientHeight)
let canvasF = ref<HTMLCanvasElement | null>(null)
let canvasTxt: any = null // 画布
let points = [] // 记录点
let startX = 0 // 开始坐标x
let startY = 0 // 开始坐标y
let moveY = 0
let moveX = 0
let strDataURI = ref('') // 保存的canvas图像
onMounted(() => {
let canvas = canvasF.value
canvas!.height = canvasClientHeight.value * 0.9
canvas!.width = canvasClientWidth.value
canvasTxt = canvasF.value!.getContext('2d');
canvasTxt.strokeStyle = '#333'
canvasTxt.lineWidth = '3'
})
const touchStart = (ev:any) => {
ev.preventDefault()
console.log(52233, ev)
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clientX,
y: ev.targetTouches[0].clientY
}
console.log(444, obj)
startX = obj.x
startY = obj.y
canvasTxt.beginPath() // 开始作画
points.push(obj) // 记录点
}
}
const touchMove = (ev:any) => {
ev.preventDefault()
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clientX,
y: ev.targetTouches[0].clientY
}
moveY = obj.y
moveX = obj.x
canvasTxt.moveTo(startX, startY) // 移动画笔
canvasTxt.lineTo(obj.x, obj.y) // 创建线条
canvasTxt.stroke() // 画线
startY = obj.y
startX = obj.x
points.push(obj) // 记录点
}
}
const touchEnd = (ev:any) => {
ev.preventDefault()
if (ev.touches.length == 1) {
let obj = {
x: ev.targetTouches[0].clientX,
y: ev.targetTouches[0].clientY
}
points.push(obj) // 记录点
points.push({ x: -1, y: -1 }) // 记录点
canvasTxt.closePath() // 收笔
canvasTxt.fill()
}
}
const overwrite = () => {
canvasTxt.clearRect(
0,
0,
canvasF.value!.width,
canvasF.value!.height
)
points = []
}
const seaveImages = async() => {
let dataBase64 = canvasF.value!.toDataURL('image/png')
const blob = await base64ImgtoFile(dataBase64)
console.log(123, blob)
strDataURI.value = window.URL.createObjectURL(blob);
showCanvas.value = false;
console.log(99964, strDataURI.value)
}
const base64ImgtoFile = (dataurl:any, filename = 'file') => {
//将base64格式分割:['data:image/png;base64','XXXX']
const arr = dataurl.split(',')
// .*? 表示匹配任意字符到下一个符合条件的字符 刚好匹配到:
// image/png
const mime = arr[0].match(/:(.*?);/)[1] //image/png
//[image,png] 获取图片类型后缀
const suffix = mime.split('/')[1] //png
const bstr = atob(arr[1]) //atob() 方法用于解码使用 base-64 编码的字符串
let n = bstr.length
const u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
}
效果图如下: