UNPKG

@kubit-ui-web/react-components

Version:

Kubit React Components is a customizable, accessible library of React web components, designed to enhance your application's user experience

127 lines 4.85 kB
import { useEffect, useRef } from 'react'; function isImageDataEqual(a, b) { if (a.width !== b.width || a.height !== b.height) { return false; } for (let i = 0; i < a.data.length; i++) { if (a.data[i] !== b.data[i]) { return false; } } return true; } export const useDraw = (onChange) => { const canvasRef = useRef(null); const context = useRef(); const isDrawing = useRef(false); const isFilled = useRef(false); const signatureStylesRef = useRef({ color: 'black', lineWidth: 2 }); const canvasInnerData = useRef(null); // reference to the canvas data before drawing const resetCanvas = () => { if (!canvasRef.current) { return; } isFilled.current = false; context.current.clearRect(0, 0, canvasRef.current.width, canvasRef.current.height); }; const setSignatureStyles = (signatureStyles) => { if (!signatureStyles) { return; } signatureStylesRef.current.color = signatureStyles.color; signatureStylesRef.current.lineWidth = signatureStyles.lineWidth; }; const startDrawing = event => { let offsetX, offsetY; if (event.type === 'touchstart' && canvasRef.current) { const { touches } = event; const { clientX, clientY } = touches[0]; const { left, top } = canvasRef.current.getBoundingClientRect(); offsetX = clientX - left; offsetY = clientY - top; } else { offsetX = event.offsetX; offsetY = event.offsetY; } canvasInnerData.current = context.current.getImageData(0, 0, canvasRef.current?.width, canvasRef.current?.height); context.current.beginPath(); context.current.moveTo(offsetX, offsetY); isDrawing.current = true; }; const draw = event => { if (!isDrawing.current) return; let offsetX, offsetY; event.preventDefault(); if (event.type === 'touchmove' && canvasRef.current) { const { touches } = event; const { clientX, clientY } = touches[0]; const { left, top } = canvasRef.current.getBoundingClientRect(); offsetX = clientX - left; offsetY = clientY - top; } else { offsetX = event.offsetX; offsetY = event.offsetY; } context.current.lineTo(offsetX, offsetY); context.current.stroke(); }; const stopDrawing = () => { const currentLayout = context.current.getImageData(0, 0, canvasRef.current?.width, canvasRef.current?.height); context.current.closePath(); isDrawing.current = false; if (!canvasInnerData.current) { return; } const isEqual = isImageDataEqual(currentLayout, canvasInnerData.current); if (!isEqual) { const dataUrl = canvasRef.current?.toDataURL(); onChange?.(dataUrl); isFilled.current = true; } }; useEffect(() => { if (canvasRef.current === null) { return; } const canvas = canvasRef.current; context.current = canvas?.getContext('2d', { willReadFrequently: true, }); if (!context.current) { return; } // Configuración del estilo del trazo context.current.strokeStyle = signatureStylesRef.current.color; context.current.lineWidth = signatureStylesRef.current.lineWidth; context.current.lineCap = 'round'; context.current.lineJoin = 'round'; // Añadir event listeners al canvas canvas?.addEventListener('mousedown', startDrawing); canvas?.addEventListener('mousemove', draw); canvas?.addEventListener('mouseup', stopDrawing); canvas?.addEventListener('mouseleave', stopDrawing); canvas?.addEventListener('touchstart', startDrawing); canvas?.addEventListener('touchmove', draw, { passive: false }); canvas?.addEventListener('touchend', stopDrawing); return () => { // Limpiar event listeners al desmontar el componente canvas?.removeEventListener('mousedown', startDrawing); canvas?.removeEventListener('mousemove', draw); canvas?.removeEventListener('mouseup', stopDrawing); canvas?.removeEventListener('mouseleave', stopDrawing); canvas?.removeEventListener('touchstart', startDrawing); canvas?.removeEventListener('touchmove', draw); canvas?.removeEventListener('touchend', stopDrawing); }; }, []); return { canvasRef, filled: isFilled.current, resetCanvas, setSignatureStyles, }; }; //# sourceMappingURL=useDraw.js.map