1.問題
微信開放社群連結
嘗試過新版canvas,在
企業微信
中籤名依然是依然斷觸,有問題的手機是iphoe15,系統版本以及企微版本微信版本均與簽名正常的手機一致,但是那個手機就是無法正常簽字,在微信中無論新舊canvas均能正常簽字
2.解決方案
既然canvas的touchmove觸發有問題,那麼就可以透過
替代canvas的touchmove
來實現,透過在canvas上覆蓋一層dom,透過這層dom的touchmove來獲取手指劃過的軌跡即可,此文章中並沒有小程式實際程式碼只是使用了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>