Solicitar firma de usuario con JavaScript y HTML en la web

Solicitar firma manuscrita con JavaScript

En este post te mostraré cómo solicitar la firma a un usuario desde la web usando JavaScript, de modo que el usuario pueda firmar como si lo hiciera en una hoja de papel.

Después podremos enviar esa firma al servidor, descargarla, colocarla en un documento, etcétera.

Documento con firma de usuario con JavaScript - Imprimir o guardar como PDF
Documento con firma de usuario con JavaScript – Imprimir o guardar como PDF

Quiero que quede claro que vamos a solicitar la firma manuscrita usando programación en la web a través de un navegador. Para ello vamos a usar el canvas.

Nota: una vez que la firma haya sido dibujada puedes enviarla a PHP, Java, Node, etcétera. En el ejemplo te mostraré cómo descargarla como imagen y colocarla en un documento.

Preparando el canvas

No voy a profundizar en cómo hacer que el usuario dibuje en el canvas, pues eso ya lo expliqué en mi post de un prototipo de Paint en JavaScript. Así que te invito a leerlo para que no tengas dudas de lo que haremos.

A continuación te muestro el canvas con los botones que van a permitir limpiarlo, descargar la firma como imagen o generar un documento con la firma.

Por cierto, recuerda que ya he explicado cómo limpiar el canvas y cómo descargar el canvas como imagen. Aquí solo me enfocaré en recoger la firma del usuario con JavaScript.

<!--

  ____          _____               _ _           _       
 |  _ \        |  __ \             (_) |         | |      
 | |_) |_   _  | |__) |_ _ _ __ _____| |__  _   _| |_ ___ 
 |  _ <| | | | |  ___/ _` | '__|_  / | '_ \| | | | __/ _ \
 | |_) | |_| | | |  | (_| | |   / /| | |_) | |_| | ||  __/
 |____/ \__, | |_|   \__,_|_|  /___|_|_.__/ \__, |\__\___|
         __/ |                               __/ |        
        |___/                               |___/         
    
____________________________________
/ Si necesitas ayuda, contáctame en \
\ https://parzibyte.me               /
 ------------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Creado por Parzibyte (https://parzibyte.me).
------------------------------------------------------------------------------------------------
            | IMPORTANTE |
Si vas a borrar este encabezado, considera:
Seguirme: https://parzibyte.me/blog/sigueme/
Y compartir mi blog con tus amigos
También tengo canal de YouTube: https://www.youtube.com/channel/UCroP4BTWjfM0CkGB6AFUoBg?sub_confirmation=1
Twitter: https://twitter.com/parzibyte
Facebook: https://facebook.com/parzibyte.fanpage
Instagram: https://instagram.com/parzibyte
Hacer una donación vía PayPal: https://paypal.me/LuisCabreraBenito
------------------------------------------------------------------------------------------------
-->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Solicitar firma de usuario - By Parzibyte</title>
    <link rel="stylesheet" href="estilo.css">
</head>

<body>
    <p>Firmar a continuación:</p>
    <canvas id="canvas"></canvas>
    <br>
    <button id="btnLimpiar">Limpiar</button>
    <button id="btnDescargar">Descargar</button>
    <button id="btnGenerarDocumento">Pasar a documento</button>
    <br>
    <a href="https://parzibyte.me/blog">By Parzibyte</a>
    <script src="script.js"></script>
</body>

</html>

Dibujar en canvas

Te dejo el código encargado de permitir que se dibuje con el mouse, aunque ya lo expliqué a profundidad en otro artículo.

// Lo demás tiene que ver con pintar sobre el canvas en los eventos del mouse
$canvas.addEventListener("mousedown", evento => {
    // En este evento solo se ha iniciado el clic, así que dibujamos un punto
    xAnterior = xActual;
    yAnterior = yActual;
    xActual = obtenerXReal(evento.clientX);
    yActual = obtenerYReal(evento.clientY);
    contexto.beginPath();
    contexto.fillStyle = COLOR_PINCEL;
    contexto.fillRect(xActual, yActual, GROSOR, GROSOR);
    contexto.closePath();
    // Y establecemos la bandera
    haComenzadoDibujo = true;
});

$canvas.addEventListener("mousemove", (evento) => {
    if (!haComenzadoDibujo) {
        return;
    }
    // El mouse se está moviendo y el usuario está presionando el botón, así que dibujamos todo

    xAnterior = xActual;
    yAnterior = yActual;
    xActual = obtenerXReal(evento.clientX);
    yActual = obtenerYReal(evento.clientY);
    contexto.beginPath();
    contexto.moveTo(xAnterior, yAnterior);
    contexto.lineTo(xActual, yActual);
    contexto.strokeStyle = COLOR_PINCEL;
    contexto.lineWidth = GROSOR;
    contexto.stroke();
    contexto.closePath();
});
["mouseup", "mouseout"].forEach(nombreDeEvento => {
    $canvas.addEventListener(nombreDeEvento, () => {
        haComenzadoDibujo = false;
    });
});

Limpiar canvas

Al inicio de todo colocamos el color de fondo en blanco para que el canvas se vea limpio. También escuchamos el clic del botón que limpia el lienzo e invocamos a esa función.

const limpiarCanvas = () => {
    // Colocar color blanco en fondo de canvas
    contexto.fillStyle = COLOR_FONDO;
    contexto.fillRect(0, 0, $canvas.width, $canvas.height);
};
limpiarCanvas();
$btnLimpiar.onclick = limpiarCanvas;

Descargar firma como imagen

Veamos el primer caso en el que el usuario quiere descargar su firma como una imagen. El código se ve así:

// Escuchar clic del botón para descargar el canvas
$btnDescargar.onclick = () => {
    const enlace = document.createElement('a');
    // El título
    enlace.download = "Firma.png";
    // Convertir la imagen a Base64 y ponerlo en el enlace
    enlace.href = $canvas.toDataURL();
    // Hacer click en él
    enlace.click();
};

Y con esto el usuario podrá descargar la firma manuscrita. Te repito que lo de convertir el canvas a imagen ya lo expliqué en otro post, regresa a los párrafos anteriores a buscarlo si tienes dudas.

Generar documento con firma de usuario

Ahora veamos otra cosa interesante. Una vez que el usuario ha firmado usando el mouse podemos pasar esa firma a un documento HTML e incrustar esa imagen. Primero veamos la plantilla del documento en cuestión:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documento con firma - By Parzibyte</title>
    <style>
        img {
            display: block;
            margin-left: auto;
            margin-right: auto;
        }
    </style>
</head>

<body>
    <h1>Título del documento</h1>
    <strong>Simple documento para demostrar cómo se puede colocar una firma del usuario</strong>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Et magnam eius reprehenderit repudiandae, veritatis
        aliquid a iste! Eos necessitatibus omnis maiores doloremque? Ipsam rem omnis saepe architecto quam molestias
        asperiores.</p>
    <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam unde veritatis, aut exercitationem in voluptatum
        aliquid rem deleniti non quas dignissimos asperiores laborum omnis similique esse, neque autem sit possimus.</p>
    <p>Quos veniam incidunt animi distinctio, itaque voluptate laudantium voluptates doloribus ipsa praesentium qui
        veritatis perferendis rerum dicta a, non esse cupiditate nemo mollitia exercitationem nesciunt explicabo,
        debitis dolores. Mollitia, similique.</p>
    <p>Deleniti sapiente rem beatae officia libero similique iste, vitae aut? Voluptatum aperiam fugit placeat adipisci,
        consequatur reiciendis voluptatem eius dolore qui. Cumque delectus iste earum, explicabo error quas rerum nam!
    </p>
    <p>Porro tempore ipsa enim a dolore explicabo totam. Quos veniam repellendus quo excepturi voluptatibus eum
        provident corrupti debitis nesciunt neque ipsa, consequatur qui illo perferendis mollitia omnis sit cum sunt.
    </p>
    <p>Aliquid saepe quod recusandae at adipisci veniam quasi delectus maiores magni fuga accusamus ex, facere, vero
        voluptatem temporibus odit maxime. Fuga assumenda suscipit repellat sapiente, porro sit repudiandae doloremque
        officiis.</p>
    <h2>A continuación la firma</h2>
    <img src="" alt="Firma del usuario" id="firma">
    <br>
    <a href="https://parzibyte.me/blog">By Parzibyte</a>
    <script>
        if (window.opener) {
            document.querySelector("#firma").src = window.opener.obtenerImagen();
            // Imprimir documento. Si no quieres imprimir, remueve la siguiente línea
            window.print();
        }
    </script>
</body>

</html>

Es un simple documento que tiene una imagen al final. Esa imagen tiene el id firma. Ahora quiero que te fijes en el script, mismo que se ve así:

if (window.opener) {
    document.querySelector("#firma").src = window.opener.obtenerImagen();
    // Imprimir documento. Si no quieres imprimir, remueve la siguiente línea
    window.print();
}

Este documento no debería abrirse por sí mismo, sino que debería tener una ventana padre; para ello es la comprobación de window.opener.

En caso de que exista ese opener entonces obtenemos el elemento de la imagen y colocamos su src como lo que regrese la función obtenerImagen del padre, y después imprimimos.

Ahora veamos la función obtenerImagen del padre, misma que se ve así:

window.obtenerImagen = () => {
    return $canvas.toDataURL();
};

La ventana hija va a solicitar al padre la imagen, y como en el padre tenemos el canvas entonces simplemente le enviamos la firma del usuario en base64, misma que será colocada en la imagen.

Todo esto ya lo he explicado a detalle en mi post de comunicación entre ventanas de JavaScript.

Poniendo todo junto

Solicitar firma de usuario con JavaScript y HTML en la web
Solicitar firma de usuario con JavaScript y HTML en la web

Te he mostrado y explicado el código más importante para solicitar la firma del usuario y después guardarla como imagen o generarla en un documento.Ya con esto puedes crear tus propios proyectos o adaptar esto según tus necesidades.

Si quieres explorar el código completo te lo dejo en GitHub, y también te dejo una demostración en línea por aquí.

Te dejo un vídeo explicando y demostrando lo expuesto en el post: https://www.youtube.com/watch?v=c4Q_Xnd_yUM

Después puedes ver cómo mejorarlo para que funcione en móviles: https://www.youtube.com/watch?v=q47YVQa2TGM

Por cierto, puedes hacer cualquier otra cosa con la imagen. En mi blog tengo un post donde explico cómo enviar un canvas a PHP. También podrías generar el PDF directamente o imprimirlo. Todo queda en ti.

Para terminar te dejo con más tutoriales de JavaScript.

Estoy aquí para ayudarte 🤝💻


Estoy aquí para ayudarte en todo lo que necesites. Si requieres alguna modificación en lo presentado en este post, deseas asistencia con tu tarea, proyecto o precisas desarrollar un software a medida, no dudes en contactarme. Estoy comprometido a brindarte el apoyo necesario para que logres tus objetivos. Mi correo es parzibyte(arroba)gmail.com, estoy como@parzibyte en Telegram o en mi página de contacto

No te pierdas ninguno de mis posts 🚀🔔

Suscríbete a mi canal de Telegram para recibir una notificación cuando escriba un nuevo tutorial de programación.

13 comentarios en “Solicitar firma manuscrita con JavaScript”

  1. Hola,tengo un formulario en el cual unos trabajadores ponen su nombre y se llevan uniforme y se resta del stock de shetts pero me gustaria añadir la firma de cada persona en ese formulario, seria posible con este codigo
    gracias

  2. Muchas gracias por el post, me ha sido muy útil.
    Una pregunta: Hay alguna manera de detectar que el canvas está vacío. me gustaría hacer esa comprobación antes de enviar la firma a la base de datos

  3. Hola
    Como se debe modificar el código para solicitar dos firmas diferentes?
    Intenté hacerlo con dos archivos de js y agregando metodos iguales con nombres diferentes en un mismo js, pero no toma en cuenta ambos campos o uno o otro 🙁

  4. Buenas,
    MUY bueno el ejemplo, el caso es que necesitaría guardar el documento firmado en una Ruta en concreto, ¿ habría forma de añadir un botón para guardaren una ruta en concreto ?

    Gracias,

    Juan Peláez

  5. Muchas gracias por este tutorial, andaba buscando algo como esto para un app interna de mi empresa y me ha venido genial.
    Pero tengo un problema, cuando le doy a generar el documento no me lleva la firma, si lo abro el inspeccionador y refresco me la trae pero como al darle a generar la firma me refresca también la otra ventana me la trae en blanco. Me puedes ayudar?

Dejar un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *