DEV Community

Xiao Ling
Xiao Ling

Posted on • Originally published at dynamsoft.com

How to Insert Signatures into PDF Documents with HTML5 and JavaScript

An e-signature is a digital form of a handwritten signature that allows individuals to sign documents electronically. It has become an essential tool for businesses and organizations to streamline the signing process, enabling documents to be signed in just a few clicks from anywhere in the world. In this article, we will explore how to insert a signature into PDF documents using HTML5, JavaScript, and Dynamsoft Document Viewer.

Demo Video: Sign PDF Documents with Electronic Signature

Online Demo

https://yushulx.me/web-document-annotation/

Prerequisites

Implementing Signature Functionality for Web PDF Editor

Our web document annotation project, built with the Dynamsoft Document Viewer, is highly extensible. It currently includes barcode detection for PDF documents. In the following sections, we will guide you through the process of adding an electronic signature to PDF documents step by step.

Step 1: Get the Source Code

  1. Clone the source code from the GitHub repository:

    git clone https://github.com/yushulx/web-twain-document-scan-management.git
    
  2. Navigate to the document_annotation directory:

    cd web-twain-document-scan-management/examples/document_annotation
    
  3. Open the project in Visual Studio Code.

Step 2: Add a Signature Button

  1. In main.css, add a material icon for the signature button:

    .icon-stylus::before {
        content: "edit";
    }
    
    .icon-stylus {
        display: flex;
        font-size: 1.5em;
    }
    
    

    stylus button

  2. Define the signature button and add it to the toolbar in main.js:

    const signatureButton = {
        type: Dynamsoft.DDV.Elements.Button,
        className: "material-icons icon-stylus",
        tooltip: "Sign the document",
        events: {
            click: "sign",
        }
    }
    
    const pcEditViewerUiConfig = {
        type: Dynamsoft.DDV.Elements.Layout,
        flexDirection: "column",
        className: "ddv-edit-viewer-desktop",
        children: [
            {
                type: Dynamsoft.DDV.Elements.Layout,
                className: "ddv-edit-viewer-header-desktop",
                children: [
                    {
                        type: Dynamsoft.DDV.Elements.Layout,
                        children: [
                            Dynamsoft.DDV.Elements.ThumbnailSwitch,
                            Dynamsoft.DDV.Elements.Zoom,
                            Dynamsoft.DDV.Elements.FitMode,
                            Dynamsoft.DDV.Elements.Crop,
                            Dynamsoft.DDV.Elements.Filter,
                            Dynamsoft.DDV.Elements.Undo,
                            Dynamsoft.DDV.Elements.Redo,
                            Dynamsoft.DDV.Elements.DeleteCurrent,
                            Dynamsoft.DDV.Elements.DeleteAll,
                            Dynamsoft.DDV.Elements.Pan,
                            Dynamsoft.DDV.Elements.AnnotationSet,
                            qrButton,
                            checkButton,
                            scanButton,
                            clearButton,
                            signatureButton,
                        ],
                    },
                    {
                        type: Dynamsoft.DDV.Elements.Layout,
                        children: [
                            {
                                type: Dynamsoft.DDV.Elements.Pagination,
                                className: "ddv-edit-viewer-pagination-desktop",
                            },
                            loadButton,
                            downloadButton,
                        ],
                    },
                ],
            },
            Dynamsoft.DDV.Elements.MainView,
        ],
    };
    
  3. Add the click event handler for the signature button:

    editViewer.on("sign", sign);
    
    function sign() {
        ...
    }
    

Step 3: Create a Pop-up Dialog for Signature Input

The pop-up dialog for signature input includes the following elements:

  • A canvas element for drawing the signature.
  • Color options for changing the signature color.
  • A stroke slider to adjust signature thickness.
  • X and Y coordinates for positioning the signature.
  • A save button to insert the signature into the PDF document.
  • A cancel button to close the dialog.
  • A redraw button to erase the signature.

HTML Code

<div id="signature-input" class="overlay">
    <div class="signature-container">
        <h2>Create New Signature</h2>
        <canvas id="signatureCanvas"></canvas>
        <div class="form-group">
            <span>Color Style:</span>
            <div id="blue" class="color-button" style="background-color: blue;"></div>
            <div id="red" class="color-button" style="background-color: red;"></div>
            <div id="black" class="color-button" style="background-color: black;"></div>
        </div>
        <div class="form-group">
            <span>Stroke:</span>
            <input type="range" id="strokeSlider" min="1" max="10" value="3">
        </div>

        <!-- X -->
        <div class="form-group">
            <label for="signatureX">X:</label>
            <input type="text" id="signatureX" name="signatureX" placeholder="0">
        </div>

        <!-- Y -->
        <div class="form-group">
            <label for="signatureY">Y:</label>
            <input type="text" id="signatureY" name="signatureY" placeholder="0">
        </div>

        <div style="margin-top: 10px;">
            <input type="checkbox" id="signatureAllPage"> Auto-generate signatures on all pages
        </div>


        <div class="popup-buttons">
            <button id="signatureOK">OK</button>
            <button id="signatureRedraw">Redraw</button>
            <button id="signatureCancel">Cancel</button>
        </div>
    </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Signature input dialog

JavaScript code for the signature input dialog

  1. Initialize the canvas and drawing context:

    let canvas = document.getElementById("signatureCanvas");
    let ctx = canvas.getContext("2d");
    let isDrawing = false;
    let color = "black"; 
    let strokeWidth = 3;  
    let drawingHistory = []; 
    canvas.width = 500;
    canvas.height = 300;
    
  2. Add event listeners for mouse events:

    canvas.addEventListener("mousedown", startDrawing);
    canvas.addEventListener("mousemove", draw);
    canvas.addEventListener("mouseup", stopDrawing);
    canvas.addEventListener("mouseout", stopDrawing);
    
  3. Add event listeners for color and stroke options:

    document.getElementById("blue").addEventListener("click", () => {
        color = "blue";
        redrawCanvas();
    });
    
    document.getElementById("red").addEventListener("click", () => {
        color = "red";
        redrawCanvas();
    });
    
    document.getElementById("black").addEventListener("click", () => {
        color = "black";
        redrawCanvas();
    });
    
    document.getElementById("strokeSlider").addEventListener("input", (e) => {
        strokeWidth = e.target.value;
        redrawCanvas();
    });
    
  4. Implement the drawing functions:

    function startDrawing(event) {
        isDrawing = true;
        let currentPath = {
            color: color,
            strokeWidth: strokeWidth,
            points: [{ x: event.offsetX, y: event.offsetY }]
        };
        drawingHistory.push(currentPath);
    }
    
    function draw(event) {
        if (isDrawing) {
            let currentPath = drawingHistory[drawingHistory.length - 1];
            currentPath.points.push({ x: event.offsetX, y: event.offsetY });
            redrawCanvas();
        }
    }
    
    function stopDrawing() {
        isDrawing = false;
    }
    
    function redrawCanvas() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
    
        drawingHistory.forEach(path => {
            ctx.beginPath();
            ctx.moveTo(path.points[0].x, path.points[0].y);
            for (let i = 1; i < path.points.length; i++) {
                ctx.lineTo(path.points[i].x, path.points[i].y);
            }
            ctx.strokeStyle = color;
            ctx.lineWidth = strokeWidth;
            ctx.stroke();
        });
    }
    
    function clearCanvas() {
        drawingHistory = [];
        redrawCanvas();
    }
    

    All paths are stored in the drawingHistory array. The redrawCanvas function iterates through the array and redraws the paths on the canvas.

  5. Add event listeners for the OK, Redraw, and Cancel buttons:

    
    const signatureOKButton = document.getElementById('signatureOK');
    const signatureRedrawButton = document.getElementById('signatureRedraw');
    const signatureCancelButton = document.getElementById('signatureCancel');
    
    signatureOKButton.addEventListener('click', async () => {
        ...
    });
    
    signatureRedrawButton.addEventListener('click', async () => {
        drawingHistory = [];
        redrawCanvas();
    });
    
    signatureCancelButton.addEventListener('click', async () => {
        document.getElementById("signature-input").style.display = "none";
    });
    

Step 4: Insert Signatures into Documents

To insert the signature into the PDF document:

  1. Convert the canvas to a blob:

    canvas.toBlob(async (blob) => {
        ...
    }, 'image/png');
    
  2. Get the current page ID and page data:

    let currentPageId = currentDoc.pages[editViewer.getCurrentPageIndex()];
    let pageData = await currentDoc.getPageData(currentPageId);
    
  3. Create new stamp annotations with the signature image:

    
    const applyToAllPages = document.getElementById("signatureAllPage").checked;
    
    const x = Number(document.getElementById("signatureX").value);
    const y = Number(document.getElementById("signatureY").value);
    
    const option = {
        stamp: blob,
        x: x > pageData.mediaBox.width - canvas.width ? pageData.mediaBox.width - canvas.width - 10 : x,
        y: y > pageData.mediaBox.height - canvas.height ? pageData.mediaBox.height - canvas.height - 10 : y,
        width: canvas.width,
        height: canvas.height,
        opacity: 1.0,
        flags: {
            print: false,
            noView: false,
            readOnly: false,
        }
    }
    
    try {
        if (applyToAllPages) {
            for (let i = 0; i < currentDoc.pages.length; i++) {
                let signatureAnnotation = await Dynamsoft.DDV.annotationManager.createAnnotation(currentDoc.pages[i], "stamp", option)
                signatureAnnotation['name'] = 'signature';
            }
        } else {
            let signatureAnnotation = await Dynamsoft.DDV.annotationManager.createAnnotation(currentPageId, "stamp", option)
            signatureAnnotation['name'] = 'signature';
        }
    } catch (e) {
        console.log(e);
    }
    

    PDF document with electronic signature

Source Code

https://github.com/yushulx/web-twain-document-scan-management/tree/main/examples/document_annotation

Top comments (0)