Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
Actas_Usuarios
/
assets
/
js
:
firmas.js
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
// assets/js/firmas.js class FirmaCanvas { constructor(canvasId, inputId, btnLimpiarId) { this.canvas = document.getElementById(canvasId); this.ctx = this.canvas.getContext('2d'); this.input = document.getElementById(inputId); this.btnLimpiar = document.getElementById(btnLimpiarId); this.dibujando = false; this._init(); this._eventos(); } _init() { // Tomamos el ancho del CONTENEDOR padre, no del canvas // Así obtenemos el ancho real ya renderizado por CSS const contenedor = this.canvas.parentElement; const ancho = contenedor.clientWidth; const alto = 160; // Asignamos tamaño CSS primero this.canvas.style.width = ancho + 'px'; this.canvas.style.height = alto + 'px'; // Luego el tamaño interno del bitmap (sin multiplicar por dpr // para evitar el desfase de coordenadas en pantallas de alta densidad) this.canvas.width = ancho; this.canvas.height = alto; this._limpiar(); } _limpiar() { this.ctx.fillStyle = '#ffffff'; this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height); this.ctx.strokeStyle = '#000000'; this.ctx.lineWidth = 2.5; this.ctx.lineCap = 'round'; this.ctx.lineJoin = 'round'; this.input.value = ''; } // Posición exacta relativa al canvas, corregida para zoom y scroll _pos(e) { const rect = this.canvas.getBoundingClientRect(); const src = e.touches ? e.touches[0] : e; // scaleX/scaleY corrige si el canvas CSS != tamaño interno del bitmap const scaleX = this.canvas.width / rect.width; const scaleY = this.canvas.height / rect.height; return { x: (src.clientX - rect.left) * scaleX, y: (src.clientY - rect.top) * scaleY }; } _start(e) { this.dibujando = true; const p = this._pos(e); this.ctx.beginPath(); this.ctx.moveTo(p.x, p.y); e.preventDefault(); } _move(e) { if (!this.dibujando) return; const p = this._pos(e); this.ctx.lineTo(p.x, p.y); this.ctx.stroke(); e.preventDefault(); } _end(e) { if (this.dibujando) { this.dibujando = false; this.input.value = this.canvas.toDataURL('image/png'); } e.preventDefault(); } _eventos() { ['mousedown', 'touchstart'].forEach(ev => this.canvas.addEventListener(ev, e => this._start(e), { passive: false })); ['mousemove', 'touchmove'].forEach(ev => this.canvas.addEventListener(ev, e => this._move(e), { passive: false })); ['mouseup', 'mouseleave', 'touchend', 'touchcancel'].forEach(ev => this.canvas.addEventListener(ev, e => this._end(e), { passive: false })); this.btnLimpiar?.addEventListener('click', () => this._limpiar()); } } // ── Inicialización ─────────────────────────────────────────────────────── document.addEventListener('DOMContentLoaded', () => { new FirmaCanvas('canvasEntrega', 'firma_entrega', 'limpiar_entrega'); new FirmaCanvas('canvasRecibe', 'firma_recibe', 'limpiar_recibe'); // Validación antes de enviar document.getElementById('form_acta')?.addEventListener('submit', e => { const fEntrega = document.getElementById('firma_entrega').value; const fRecibe = document.getElementById('firma_recibe').value; if (!fEntrega) { e.preventDefault(); alert('⚠️ Debe dibujar la firma de quien entrega.'); return; } if (!fRecibe) { e.preventDefault(); alert('⚠️ Debe dibujar la firma de quien recibe.'); } }); });