vue3 + canvas 手写签名

代码如下:

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
    })
}

效果图如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值