对于小程序canvas在某些情况下touchmove 不能连续触发导致的签名不连续替代方案(企微)
1.问题
不正常版本
正常版本
尝试过新版canvas,在
企业微信
中签名依然是依然断触,有问题的手机是iphoe15,系统版本以及企微版本微信版本均与签名正常的手机一致,但是那个手机就是无法正常签字,在微信中无论新旧canvas均能正常签字
===========================
后期发现由于网络问题,获取到的微信lib库版本有问题,虽然vconsole中的版本一致但是时间不一致,没有问题的时间是2024年,有问题的是2024年,而切换到5g网络不使用公司内部网络则没有问题,很神奇,具体原因暂时未找到
2.解决方案
既然canvas的touchmove触发有问题,那么就可以通过
替代canvas的touchmove
来实现,通过在canvas上覆盖一层dom,通过这层dom的touchmove来获取手指划过的轨迹即可,此文章中并没有小程序实际代码只是使用了h5验证可行性的代码
还可以使用webview内嵌h5网页
,这个内嵌网页可以正常使用canvas的touchmove,因为小程序的canvas与webview用的不是同一个,但是这样处理多了要从h5传递图像信息到小程序端
2.1 注意点
- 要区别手指是否连续滑动,由于点击事件触发存在如下情况
区别手指是否连续滑动采用时间间隔判断
触发事件间隔小于80ms 主要用于判断是否松开手指再次滑动,正常手速来说80ms,人很难在画完一个线段后,松手再次画一个线段,如果无这个处理会出现滑动一个线段之后,再次点击另一个点会把线段和新点位连接起来
没有采取通过touchstart与touchend做一个判断是因为touchmove并不是固定一直在start与end事件中间触发
2.2 移动端浏览器体验地址
2.2 vue2代码
<template> <div class="DomCanvasSignature"> <div :style="{ height: height + 'px', width: width + 'px' }" class="signatureWrapper" id="signatureWrapper" draggable="false" @mousedown="touchstart" @mouseup="touchend" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove" @mousemove="touchmove"> <canvas canvas-id="999" :height="height" :width="width - 3" class="canvas" /> </div> </div> </template> <script> export default { name: 'DomCanvasSignature', data () { return { height: 302, width: 302, mycanvas: null, previousPoint: { x: 0, y: 0 }, isPcStart: false, removeLisner: () => { } } }, methods: { initSize () { this.width = window.innerWidth this.height = window.innerHeight - 300 }, lisner () { this.initSize() window.addEventListener('resize', this.initSize) return () => { window.removeEventListener('resize', this.initSize) } }, touchstart () { this.isPcStart = true console.log('====start') // zdz-log }, touchend () { this.isPcStart = false console.log('====end') // zdz-log }, touchmove (e) { console.log('move', e) // zdz-log // 阻止滚动 e.preventDefault() if (e.type === 'mousemove' && !this.isPcStart) { return } // 合并处理 pc 与移动端 const changeObj = e.changedTouches && e.changedTouches[0] || e const current = { x: changeObj.clientX, y: changeObj.clientY, timeStamp: e.timeStamp } // 1.获取元素 // 2.获取上下文,绘制工具箱 let ctx = this.mycanvas.getContext('2d') // 3.移动画笔 const currentY = (current.y) - signatureWrapper.offsetTop // todo 改为touchstart 与end判断 无法实现 因为move 执行存在在 start end事件之后 let diffLarge = false console.log(current.timeStamp - this.previousPoint.timeStamp) // zdz-log // 判断是否松手重新绘制 if (this.previousPoint.timeStamp) { const timeDiff = current.timeStamp - this.previousPoint.timeStamp > 80 if (timeDiff) { diffLarge = true } } const preY = diffLarge ? current.y - signatureWrapper.offsetTop : (this.previousPoint.y || current.y) - signatureWrapper.offsetTop const moveX = diffLarge ? current.x : this.previousPoint.x || current.x ctx.moveTo(moveX, preY < 0 ? 0 : preY) // 4.绘制直线(轨迹,绘制路径) ctx.lineTo(current.x, currentY < 0 ? 0 : currentY) // 5.描边 ctx.stroke() this.previousPoint = current }, }, created () { this.removeLisner = this.lisner() }, destroyed () { this.removeLisner() }, mounted () { this.mycanvas = document.querySelector('canvas') this.signatureWrapper = document.getElementById('signatureWrapper') }, } </script> <style scoped> .canvas { border: 1px solid red; } .signatureWrapper { display: flex; align-items: center; justify-content: center; border: 1px solid black; background-color: transparent; } </style>
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤