szimek / signature_pad

HTML5 canvas based smooth signature drawing
http://szimek.github.io/signature_pad/
MIT License
10.93k stars 2.11k forks source link

signature pad won't display signature if hidden on initial page load, then revealed by jQuery slideDown #485

Closed wmalexander closed 2 years ago

wmalexander commented 4 years ago

The form with the signature pad is hidden on page load, later revealed with jQuery slideDown. When this is in effect, no signature works on the pad. When "display: none" is removed from the form for the initial page load, all works as expected. Here's a demo:

https://www.loom.com/share/8865cf1cc93145f1ac017ae1915edd69

No console errors. What am I doing wrong?

chatzikk commented 4 years ago

Is there any solution for this issue as I have the same problem?

lexandclo commented 4 years ago

Same here, if i only dev console on browser and close again it works fine, but not on page load

adsheff commented 4 years ago

There are a few issues with it when it is hidden and shown. One solution is to call $(window).resize(); after the slideDown - which reinitialises the signature Pad. Don't really know the ins and outs but this works for me.

sofiiahitlan commented 3 years ago

Another option I found elsewhere is to position your form way off the screen (-5000px) instead of using display: none;. When ready to display it, change the margin to the positive value.

Any of the CSS manipulations, including the one I mentioned above, didn't work for me. Instead of playing with CSS, I didn't render the signature pad until the user was ready to sign. i.e. wrap the signature pad component with the condition that listens to some event.

dennisMeeQ commented 3 years ago

Had the same issue. The problem was that the container displaying the signature pad was hidden with display: none while the signature pad was rendering. My (hacky) solution was to wait until the container was rendered and only then render the signature pad.

UziTech commented 2 years ago

closing as stale

Vladimir-Romanets commented 1 year ago

The problem is we need to reinitialise canvas with some value when it shown in our DOM. So we need do next:

  1. Detect if the canvas visible (not mounted).
  2. Run reinitialising canvas process if it became visible.

So, here is my solution:

  1. I use hook to detect if element visible (https://stackoverflow.com/questions/45514676/react-check-if-element-is-visible-in-dom, thankfully GuCier)
function useOnScreen(ref: React.MutableRefObject<HTMLCanvasElement>) {
  const [isIntersecting, setIntersecting] = useState(false);

  const observer = useMemo(
    () =>
      new IntersectionObserver(([entry]) =>
        setIntersecting(entry.isIntersecting)
      ),
    []
  );

  useEffect(() => {
    observer.observe(ref.current);

    return observer.disconnect;
  }, []);

  return isIntersecting;
}
  1. Run reinitialising canvas process for SignaturePad component:
    
    ...
    const isVisible = useOnScreen(canvasRef);
    ....
    useEffect(() => {
      if (isVisible) {
        resizeCanvas(canvasRef.current, signaturePadInstance);
      }
    }, [isVisible]);
    ...