Form with graphic signature

Good morning everybody, I should develop a system to allow a client to sign a form through their smartphone, simply with the finger
In the past someone has asked for similar information but I have not found any specific advice.
The form could, in my opinion, behave in two ways:
-write information and then create an image from the user’s signature and upload by FTP
-or convert the image to base64, write it in the database and then have a way to reconvert it again and show it as jpg to the client.
I have never done anything like this and so I would like to know if any of you have had to face this problem.
Using asp.net on Windows servers and testing locally on IIS.
Thank you!

Hi Mark,

I recommend you explain the two ways again because it isn't easy to understand

Browsers can show base64-encoded images if that's what you're looking for, probably you just need a dmx-bind to bind the Base64 data to a certain attribute in the img tag

Sorry for my bad english!!!
I have found a solution for those who are interested.
I put in the form a field 'canvas' before 'submit'

<canvas id="signatureCanvas" width="400" height="200" class="border rounded w-100"></canvas>
<input type="hidden" id="firma_base64" name="firma">

then its JS code (thanks to ChatGPT :slight_smile: )

<script>
              document.addEventListener('DOMContentLoaded', function() {
    const canvas = document.getElementById('signatureCanvas');
    const ctx = canvas.getContext('2d');
    const clearButton = document.getElementById('clearButton');
    const firmaInput = document.getElementById('firma_base64');
    const form = document.querySelector('form');
    
    canvas.width = 800;
    canvas.height = 300;
    
    let isDrawing = false;
    let hasSignature = false;
    let lastX = 0;
    let lastY = 0;

    ctx.strokeStyle = '#000000';
    ctx.lineWidth = 2;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';

    function getCoordinates(e) {
        const rect = canvas.getBoundingClientRect();
        const scaleX = canvas.width / rect.width;
        const scaleY = canvas.height / rect.height;
        
        let clientX, clientY;
        
        if (e.type.includes('touch')) {
            clientX = e.touches[0].clientX;
            clientY = e.touches[0].clientY;
        } else {
            clientX = e.clientX;
            clientY = e.clientY;
        }
        
        return [
            (clientX - rect.left) * scaleX,
            (clientY - rect.top) * scaleY
        ];
    }

    function updateBase64() {
        try {
            const signatureData = canvas.toDataURL('image/png');
            firmaInput.value = signatureData;
            hasSignature = true;
            console.log('Firma salvata:', signatureData.substring(0, 50) + '...');
        } catch (error) {
            console.error('Errore nel salvataggio della firma:', error);
        }
    }

    function startDrawing(e) {
        e.preventDefault();
        isDrawing = true;
        hasSignature = true;
        [lastX, lastY] = getCoordinates(e);
    }

    function draw(e) {
        if (!isDrawing) return;
        e.preventDefault();

        const [currentX, currentY] = getCoordinates(e);

        ctx.beginPath();
        ctx.moveTo(lastX, lastY);
        ctx.lineTo(currentX, currentY);
        ctx.stroke();

        [lastX, lastY] = [currentX, currentY];
        
        // Aggiorna la firma durante il disegno
        updateBase64();
    }

    function stopDrawing(e) {
        if (isDrawing) {
            isDrawing = false;
            // Forza l'aggiornamento della firma quando si smette di disegnare
            updateBase64();
        }
    }

    // Event listeners per mouse
    canvas.addEventListener('mousedown', startDrawing);
    canvas.addEventListener('mousemove', draw);
    canvas.addEventListener('mouseup', stopDrawing);
    canvas.addEventListener('mouseout', stopDrawing);

    // Event listeners per touch
    canvas.addEventListener('touchstart', startDrawing, { passive: false });
    canvas.addEventListener('touchmove', draw, { passive: false });
    canvas.addEventListener('touchend', stopDrawing);
    canvas.addEventListener('touchcancel', stopDrawing);

    // Previeni lo scroll
    canvas.addEventListener('touchmove', function(e) {
        e.preventDefault();
    }, { passive: false });

    // Pulisci canvas
    clearButton.addEventListener('click', function() {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        firmaInput.value = '';
        hasSignature = false;
    });

    // Controllo prima del submit
    form.addEventListener('submit', function(e) {
        if (hasSignature) {
            // Forza un ultimo aggiornamento della firma prima del submit
            updateBase64();
        }
    });
});
            </script>

in the database is saved in image64 format, so in the view page I show it with:

<div align="center"><img dmx-bind:src="'data:image/jpeg;base64,'+data_detail1.data.firma" dmx-show="data_detail1.data.firma"></div>
1 Like