From c4e114fc3327c439d939cb18519f643c340a9c0d Mon Sep 17 00:00:00 2001 From: neverland Date: Mon, 1 May 2023 16:40:44 +0800 Subject: [PATCH] fix(Signature): failed to sign in mobile devices (#11797) --- packages/vant/src/signature/Signature.tsx | 61 +++++++++---------- .../vant/src/signature/test/index.spec.ts | 6 +- 2 files changed, 32 insertions(+), 35 deletions(-) diff --git a/packages/vant/src/signature/Signature.tsx b/packages/vant/src/signature/Signature.tsx index 96d8e3def..358bd70d0 100644 --- a/packages/vant/src/signature/Signature.tsx +++ b/packages/vant/src/signature/Signature.tsx @@ -12,6 +12,7 @@ import { createNamespace, preventDefault, } from '../utils'; +import { useRect } from '@vant/use'; import { Button } from '../button'; const [name, bem, t] = createNamespace('signature'); @@ -45,43 +46,11 @@ export default defineComponent({ width: 0, height: 0, ctx: null as CanvasRenderingContext2D | null | undefined, - isSupportTouch: 'ontouchstart' in window, }); + let canvasRect: DOMRect; const isRenderCanvas = inBrowser ? hasCanvasSupport() : true; - const touchMove = (event: TouchEvent) => { - if (!state.ctx) { - return false; - } - - preventDefault(event); - - const evt = event.changedTouches - ? event.changedTouches[0] - : event.targetTouches[0]; - - emit('signing', evt); - let mouseX = evt.clientX; - let mouseY = evt.clientY; - - if (!state.isSupportTouch) { - const coverPos = canvasRef.value?.getBoundingClientRect(); - mouseX = evt.clientX - (coverPos?.left || 0); - mouseY = evt.clientY - (coverPos?.top || 0); - } - - state.ctx.lineCap = 'round'; - state.ctx.lineJoin = 'round'; - state.ctx?.lineTo(mouseX, mouseY); - state.ctx?.stroke(); - }; - - const touchEnd = (event: TouchEvent) => { - preventDefault(event); - emit('end'); - }; - const touchStart = () => { if (!state.ctx) { return false; @@ -90,9 +59,35 @@ export default defineComponent({ state.ctx.beginPath(); state.ctx.lineWidth = props.lineWidth; state.ctx.strokeStyle = props.penColor; + canvasRect = useRect(canvasRef); + emit('start'); }; + const touchMove = (event: TouchEvent) => { + if (!state.ctx) { + return false; + } + + preventDefault(event); + + const touch = event.touches[0]; + const mouseX = touch.clientX - (canvasRect?.left || 0); + const mouseY = touch.clientY - (canvasRect?.top || 0); + + state.ctx.lineCap = 'round'; + state.ctx.lineJoin = 'round'; + state.ctx?.lineTo(mouseX, mouseY); + state.ctx?.stroke(); + + emit('signing', event); + }; + + const touchEnd = (event: TouchEvent) => { + preventDefault(event); + emit('end'); + }; + const isCanvasEmpty = (canvas: HTMLCanvasElement) => { const empty = document.createElement('canvas'); empty.width = canvas.width; diff --git a/packages/vant/src/signature/test/index.spec.ts b/packages/vant/src/signature/test/index.spec.ts index 8e66b45c1..c93b722c8 100644 --- a/packages/vant/src/signature/test/index.spec.ts +++ b/packages/vant/src/signature/test/index.spec.ts @@ -21,11 +21,13 @@ test('should emit "signing" event when touch is moving', async () => { await canvas.trigger('touchstart'); await canvas.trigger('touchmove', { - changedTouches: [{ clientX: 10, clientY: 20 }], + touches: [{ clientX: 10, clientY: 20 }], }); expect(wrapper.emitted('signing')).toBeTruthy(); - expect(wrapper.emitted('signing')![0][0]).toMatchObject({ + expect( + wrapper.emitted('signing')![0][0].touches[0] + ).toMatchObject({ clientX: 10, clientY: 20, });