Signature_pad: resizing clears the pad but isEmpty() still returns false

Created on 12 Mar 2015  ·  11Comments  ·  Source: szimek/signature_pad

1) Draw on canvas
2) Resize -> Canvas clears up
3) isEmpty() returns false and the empty canvas can be submitted.

Can be reproduced at http://szimek.github.io/signature_pad/

Maybe SignaturePad should watch changes on canvas? That way user wouldn't be able to pass en empty signature.

bug

Most helpful comment

I ended up adding 2 lines to the resizecanvas() as below and it has worked so far smoothly in IE/FF/Chrome-

function resizeCanvas() {
    // When zoomed out to less than 100%, for some very strange reason,
    // some browsers report devicePixelRatio as less than 1
    // and only part of the canvas is cleared then.

    var data = signaturePad.toDataURL(); //Added

    var ratio = Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = canvas.offsetWidth * ratio;
    canvas.height = canvas.offsetHeight * ratio;
    canvas.getContext("2d").scale(ratio, ratio);

    signaturePad.fromDataURL(data); //Added
}

All 11 comments

I'm not sure if it's possible to watch changes on canvas... maybe with MutationObserver, but that wouldn't work in IE10 and earlier. Maybe it could simply expose a function that you can call when you resize the canvas element to let the library know that something has changed? Or both - expose a function and use MutationObserver to call it automatically on supported browsers...

Workaround is not too difficult, though. I've added a SignaturePad.clear() call at the end of the resize routine and that pretty much solves the issue.

I forgot that #clear already sets isEmpty to true :) Anyway, it's probably a good idea to call #clear in the demo page as well with a comment why it's there, so I'll leave it open till I have time to do it.

All in all, because of this and issue #32 I ended up using a helper variable, hasSignature as follows.

        signaturePad = new SignaturePad(canvas, {
            onEnd: function() {
                hasSignature = true;
            }
        });

and

clearButtonAction = function () {
    hasSignature = false;
    signaturePad.clear();
}

With that I could then proceed to mark canvas as clear, or, when a signature is present, copy-paste the signature.

        var resizeCanvas = function () {
            if (hasSignature) {
                signatureCopy = signaturePad.toDataURL();
            }

            var ratio = window.devicePixelRatio || 2;

            // Note fixed width:height ratio. No need for dynamic height.       
            canvas.width = canvas.offsetWidth * ratio;
            canvas.height = Math.floor(canvas.offsetWidth/3) * ratio; 
            canvas.getContext("2d").scale(ratio, ratio);

            // Line width is relative to canvas size to prevent different
            // width after orientation changes.
            signaturePad.minWidth = canvas.offsetWidth / 1000;
            signaturePad.maxWidth = signaturePad.minWidth * 5;

            if (hasSignature) {
                signaturePad.fromDataURL(signatureCopy);
            } else {
                // signaturePad doesn't watch canvas and needs to be told it's clear now
                signaturePad.clear(); 
            }
        }

As mentioned in #32, copy ends up a bit blurred but it's a whole lot better than losing the signature altogether.

Anyways, thanks a ton for a great piece of software, Szymon!

From my point of view, this resizing should be handled internally somehow, I mean when the page resizes, the canvas should autodraw itself.

This works a lot better if you store signatureCopy in the onEnd callback (along with the hasSignature, or better yet, use signatureCopy to determine if you have one or not by nulling it in the clear method). Since resize fires multiple times in many browsers, this stops you from ending up with a super low quality signature that's been resized multiple times.

Having the same problem: when resizing the signature is lost, can be reproduced at http://szimek.github.io/signature_pad/

I ended up adding 2 lines to the resizecanvas() as below and it has worked so far smoothly in IE/FF/Chrome-

function resizeCanvas() {
    // When zoomed out to less than 100%, for some very strange reason,
    // some browsers report devicePixelRatio as less than 1
    // and only part of the canvas is cleared then.

    var data = signaturePad.toDataURL(); //Added

    var ratio = Math.max(window.devicePixelRatio || 1, 1);
    canvas.width = canvas.offsetWidth * ratio;
    canvas.height = canvas.offsetHeight * ratio;
    canvas.getContext("2d").scale(ratio, ratio);

    signaturePad.fromDataURL(data); //Added
}

@niteshluharuka Do you encounter this issue whereby the signature gets blurry upon resize?

Before resize

After resize

@iamjoyce no, it was a different issue of the entire canvas getting cleared. never encountered blurry issue :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

auam88 picture auam88  ·  4Comments

kevinchung1026 picture kevinchung1026  ·  5Comments

hostcia picture hostcia  ·  6Comments

50l3r picture 50l3r  ·  3Comments

davidosuna1987 picture davidosuna1987  ·  11Comments