vue3 手机端 手写签字
<template> <div> <div> <canvas class="canvas" id="canvas" ref="canvas"></canvas> <canvas id="blank" style="display: none"></canvas> <p v-else style="font-size: 240px; line-height: 360px"> 请适当放慢签写速度,确保字迹清晰可辨认! </p> <div class="button"> <div class="signature"> <button class="re-sign" ref="clearBtn">重新签名</button> </div> <div class="signature"> <button class="re-sign" @click="imgcanvas">提交签名</button> </div> </div> <!-- <img :src="dataURL" alt="" /> --> </div> </div> </template>
<script setup> import { onMounted, ref } from 'vue' import axios from 'axios'
const canvas = ref(null) let ctx = ref() let canvasWidth = document.body.clientWidth let canvasHeight = canvasWidth
const initContext = () => { ctx = canvas.value.getContext('2d') canvas.value.width = canvasWidth * 0.98 canvas.value.height = canvasHeight * 0.98 } let isDrawing = false let lastX = 0 let lastY = 0 // 重新写 let clearBtn = ref(null) onMounted(() => { initContext() canvas.value.addEventListener('touchstart', function (e) { isDrawing = true e.preventDefault() ;[lastX, lastY] = [e.changedTouches[0].clientX, e.changedTouches[0].clientY] }) canvas.value.addEventListener('touchmove', function (e) { e.preventDefault() if (isDrawing) { ctx.beginPath() ctx.lineWidth = 24 ctx.strokeStyle = '#007768' ctx.moveTo(lastX, lastY) ctx.lineTo(e.changedTouches[0].clientX, e.changedTouches[0].clientY) ctx.stroke() ;[lastX, lastY] = [e.changedTouches[0].clientX, e.changedTouches[0].clientY] } }) canvas.value.addEventListener('touchend', function () { e.preventDefault() isDrawing = false }) clearBtn.value.addEventListener('click', function () { ctx.clearRect(0, 0, canvas.value.width, canvas.value.height) }) }) const dataURL = ref() const reader = ref() const successing = ref(false) //验证canvas画布是否为空 function isCanvasBlank(canvas) { var blank = document.createElement('canvas') //系统获取一个空canvas对象 blank.width = canvas.width blank.height = canvas.height return canvas.toDataURL() == blank.toDataURL() //比较值相等则为空 } // 转换为文件 let flies = ref() const imgcanvas = async () => { var c = document.getElementById('canvas') // 获取html的canvas对象 if (isCanvasBlank(c)) { alert('请签名,签名后即可提交') return } dataURL.value = canvas.value.toDataURL('image/png') flies.value = base64ImgtoFile(dataURL.value) try { UploadFile(flies.value) } catch (error) { console.error('上传失败:', error) } } const base64ImgtoFile = (dataurl, filename = 'file') => { let arr = dataurl.split(',') let mime = arr[0].match(/:(.*?);/)[1] let suffix = mime.split('/')[1] let bstr = atob(arr[1]) let n = bstr.length let u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } return new File([u8arr], `${filename}.${suffix}`, { type: mime }) } //file上传至服务器 let dataimg = ref() const UploadFile = (file) => { let uploadkey = localStorage.getItem('uploadkey') let fd = new FormData() fd.append('file', file) //传文件 fd.append('type', '3') //传文件 axios.post('地址', fd).then((res) => { //data为后端返回的上传结果,里面包含文件在服务器上的地址 dataimg.value = res.data.data //oss返回的地址 }) } </script>