对于小程序canvas在某些情况下touchmove 不能连续触发导致的签名不连续替代方案(企微)

1.问题

image
微信开放社区链接

不正常版本image
正常版本image

尝试过新版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>
posted @   story.Write(z)  阅读(407)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 2 本地部署DeepSeek模型构建本地知识库+联网搜索详细步骤
点击右上角即可分享
微信分享提示