window.receiverSignature = (() => { const pads = new Map(); const typedSignatures = new Map(); const imageSignatures = new Map(); function getPosition(canvas, event) { const rect = canvas.getBoundingClientRect(); const source = event.touches && event.touches.length ? event.touches[0] : event; return { x: (source.clientX - rect.left) * (canvas.width / rect.width), y: (source.clientY - rect.top) * (canvas.height / rect.height) }; } function clearCanvas(canvas) { canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); } function initialize(canvasId) { const canvas = document.getElementById(canvasId); if (!canvas || pads.has(canvasId)) return; const context = canvas.getContext('2d'); context.lineWidth = 2.5; context.lineCap = 'round'; context.lineJoin = 'round'; context.strokeStyle = '#111'; const state = { drawing: false, hasSignature: false }; pads.set(canvasId, state); const start = event => { event.preventDefault(); const pos = getPosition(canvas, event); state.drawing = true; context.beginPath(); context.moveTo(pos.x, pos.y); }; const move = event => { if (!state.drawing) return; event.preventDefault(); const pos = getPosition(canvas, event); context.lineTo(pos.x, pos.y); context.stroke(); state.hasSignature = true; }; const end = event => { if (!state.drawing) return; event.preventDefault(); state.drawing = false; }; canvas.addEventListener('mousedown', start); canvas.addEventListener('mousemove', move); window.addEventListener('mouseup', end); canvas.addEventListener('touchstart', start, { passive: false }); canvas.addEventListener('touchmove', move, { passive: false }); canvas.addEventListener('touchend', end, { passive: false }); } function initializeTyped(canvasId) { const canvas = document.getElementById(canvasId); if (!canvas || typedSignatures.has(canvasId)) return; typedSignatures.set(canvasId, { hasSignature: false }); } function initializeImage(inputId, canvasId) { const input = document.getElementById(inputId); const canvas = document.getElementById(canvasId); if (!input || !canvas || imageSignatures.has(canvasId)) return; const state = { hasSignature: false }; imageSignatures.set(canvasId, state); input.addEventListener('change', () => { const file = input.files && input.files.length ? input.files[0] : null; if (!file || !file.type.startsWith('image/')) { clearCanvas(canvas); state.hasSignature = false; return; } const reader = new FileReader(); reader.onload = () => { const image = new Image(); image.onload = () => { const context = canvas.getContext('2d'); clearCanvas(canvas); const padding = 10; const maxWidth = canvas.width - padding * 2; const maxHeight = canvas.height - padding * 2; const scale = Math.min(maxWidth / image.width, maxHeight / image.height, 1); const width = image.width * scale; const height = image.height * scale; const x = (canvas.width - width) / 2; const y = (canvas.height - height) / 2; context.drawImage(image, x, y, width, height); state.hasSignature = true; }; image.src = reader.result; }; reader.readAsDataURL(file); }); } function clear(canvasId) { const canvas = document.getElementById(canvasId); const state = pads.get(canvasId); if (!canvas || !state) return; clearCanvas(canvas); state.hasSignature = false; } function clearTyped(canvasId) { const canvas = document.getElementById(canvasId); const state = typedSignatures.get(canvasId); if (!canvas || !state) return; clearCanvas(canvas); state.hasSignature = false; } function clearImage(inputId, canvasId) { const input = document.getElementById(inputId); const canvas = document.getElementById(canvasId); const state = imageSignatures.get(canvasId); if (!canvas || !state) return; if (input) input.value = ''; clearCanvas(canvas); state.hasSignature = false; } function renderTypedSignature(canvasId, text, fontFamily) { const canvas = document.getElementById(canvasId); const state = typedSignatures.get(canvasId); if (!canvas || !state) return; const value = (text || '').trim(); clearCanvas(canvas); if (!value) { state.hasSignature = false; return; } const context = canvas.getContext('2d'); const maxWidth = canvas.width - 30; let fontSize = 54; do { context.font = `italic ${fontSize}px ${fontFamily || 'cursive'}`; fontSize -= 2; } while (context.measureText(value).width > maxWidth && fontSize > 24); context.fillStyle = '#111'; context.textBaseline = 'middle'; context.textAlign = 'center'; context.fillText(value, canvas.width / 2, canvas.height / 2); state.hasSignature = true; } function getDataUrl(canvasId) { const canvas = document.getElementById(canvasId); const state = pads.get(canvasId); if (!canvas || !state || !state.hasSignature) return null; return canvas.toDataURL('image/png'); } function getTypedDataUrl(canvasId) { const canvas = document.getElementById(canvasId); const state = typedSignatures.get(canvasId); if (!canvas || !state || !state.hasSignature) return null; return canvas.toDataURL('image/png'); } function getImageDataUrl(canvasId) { const canvas = document.getElementById(canvasId); const state = imageSignatures.get(canvasId); if (!canvas || !state || !state.hasSignature) return null; return canvas.toDataURL('image/png'); } return { initialize, initializeTyped, initializeImage, clear, clearTyped, clearImage, renderTypedSignature, getDataUrl, getTypedDataUrl, getImageDataUrl }; })();