Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 1x 1x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 2x 1x 1x 1x 1x 1x 1x 1x 1x 1x 2x | import React, { useEffect, useRef, useId, forwardRef, useImperativeHandle } from 'react'; import { getBoundingClientRect, getClinetXY, useEvent } from '../utils'; import { SignatureCanvasRef, SignatureProps } from '.'; import { useDispatch } from '../store'; import { useOptionDispatch } from '../options'; export const defaultStyle: React.CSSProperties = { '--w-signature-background': '#fff', touchAction: 'none', position: 'relative', backgroundColor: 'var(--w-signature-background)', } as React.CSSProperties; export const Signature = forwardRef<SignatureCanvasRef, SignatureProps>((props, ref) => { const { className, prefixCls = 'w-signature', style, readonly = false, onPointer, options, children, ...others } = props; const cls = [className, prefixCls].filter(Boolean).join(' '); const $canvas = useRef<HTMLCanvasElement>(null); const $path = useRef<SVGPathElement>(); const pointsRef = useRef<number[][]>(); const pointCount = useRef<number>(0); const pointId = useId(); const dispatch = useDispatch(); const dispatchOption = useOptionDispatch(); useImperativeHandle<SignatureCanvasRef, SignatureCanvasRef>( ref, () => ({ canvas: $canvas.current, dispatch, clear: () => { dispatch({}); const ctx = $canvas.current?.getContext('2d'); ctx?.clearRect(0, 0, $canvas.current?.width || 0, $canvas.current?.height || 0); }, }), [$canvas.current, dispatch], ); const handlePointerDown = useEvent((e: React.PointerEvent<HTMLCanvasElement>) => { if (readonly) return; pointCount.current += 1; const { offsetY, offsetX } = getBoundingClientRect($canvas.current); const clientX = e.clientX || e.nativeEvent.clientX; const clientY = e.clientY || e.nativeEvent.clientY; pointsRef.current = [[clientX - offsetX, clientY - offsetY]]; const pathElm = document.createElementNS('http://www.w3.org/2000/svg', 'path'); $path.current = pathElm; $canvas.current!.appendChild(pathElm); dispatch({ [pointId + pointCount.current]: pointsRef.current, }); }); const handlePointerMove = useEvent((e: PointerEvent) => { if ($path.current) { const { offsetY, offsetX } = getBoundingClientRect($canvas.current); const { clientX, clientY } = getClinetXY(e); pointsRef.current = [...pointsRef.current!, [clientX - offsetX, clientY - offsetY]]; dispatch({ [pointId + pointCount.current]: pointsRef.current, }); } }); const handlePointerUp = useEvent(() => { let result = pointsRef.current || []; onPointer && props.onPointer!(result); $path.current = undefined; pointsRef.current = undefined; }); useEffect(() => { Eif ($canvas.current) { dispatchOption({ container: $canvas.current }); } Iif (readonly) return; document.addEventListener('pointermove', handlePointerMove); document.addEventListener('pointerup', handlePointerUp); return () => { Iif (readonly) return; document.removeEventListener('pointermove', handlePointerMove); document.removeEventListener('pointerup', handlePointerUp); }; }, []); return ( <canvas {...others} ref={$canvas} className={cls} onPointerDown={handlePointerDown} style={{ ...defaultStyle, ...style }} > {children} </canvas> ); }); |