Try signing this pad with your mouse
Wanted: Embeddable Signatures
Rocket Lease provides rental application software so landlords can screen their tenants with an online application rather than a paper application.
I wanted to incorporate a digital signing process into the application similar to the iPad payment kiosks that allow you to trace your signature with your finger. That's not a requirement for online signature validity, but it more closely mirrors the paper signature process that landlords are used to and there's something about physically drawing your signature that makes many people feel like it's more legitimate. (Electronic signature validity is a whole separate blog post)
I generally try to borrow rather than build, but since nothing seemed to fit the bill, I looked into customizing an existing open source solution. For Rocket Lease, if that reduces objections to using an online application, that's a win. Plus, it just seemed like fun.
Existing solutions at the time either:
- Required me to direct my users away to a third party site/service for signing
- Charged more than I wanted to pay
- Didn't have the signature smoothing component
My fork is available on my github here: https://github.com/ezl/signature-pad
Signatures are basically recorded as a series of (x,y) coordinates on a canvas, which can later be used to regenerate the signature.
However, an array of (x,y) coordinates doesn't capture the curves of a signature. if the sampling rate isn't sufficiently fast, you'll end up with jagged line segments.
Thomas Bradley's signature library seemed to be the most active, best supported, best documented open source library, but the rendering approach left jagged signatures and I wanted the smooth style signatures I was seeing in other apps (that I would have to pay for).
Try signing this canvas using the original library, which draws linear segments between sampled points:
Example: Linear Interpolation (Original)
Using the blog post by Square as a guide, I compute bezier curves (this is the same thing as the pen tool in Photoshop) that pass through the sampled points, then retrace it when the pen lifts. There are a few complications, which I'll describe below.
Example: Bezier Curves (constant pen width)
The first problem I ran into was that the sampling rate was actually too FAST. With a touchpad, there is some measurement noise that causes some of the jagged lines in the original library. Smoothing the curves removes the angles, but it still renders a wavy/squiggly signature. To counter that, I use only a subset of the sampled points, which are uniformly sampled (There are smarter approaches, but this was the easiest and least invasive to the original library).
When drawing linear segments between sampled points, you can immediately stroke a path from the n-1th point to the nth (last) point. You'll end up with the jagged linear segment approximation of a signature as described above, but the benefit is that "ink" stroke ends where your mouse cursor is, much like the ink path of a signature of a pen on paper.
With bezier curves, however, the last 2 points are insufficient for determining the shape of the arc between the last 2 points. Given the last 2 sampled points n-1 and n, we actually need to know the location of point n-2 (the third to last point we sampled -- we know this) and n+1 (the next point that WILL be sampled in the future -- obviously we *don't* know this) to trace the correct Bezier curve.
So to draw the right segment, you always have to be lagging the mouse cursor in order to trace the correct path, which makes the signature feel less responsive to the end user.
To resolve this, I'm stroking the sampled path with linear segments, then once there is enough information to render the curve, I erase the linear segments and stroke a bezier in it's path. Erasing by drawing a white line over the original segments weirdly doesn't cover up the previous line though and it results in weird "ghost" markings that outline where the previous segments were.
You'll notice this if you try signing the smoothed pad above again. To highlight it, just scribble over the whole pad many times and you'll see what I'm referring to. The hacky "fix" for this was to restroke the sampled path on the mouseup (or touchend) event.
Regenerating Smooth Signatures
Finally, just an example of 2 signatures the difference between the 2 methods of rendering signatures.
These signatures are generated from the same underlying data.
If you look closely, you'll see that there are kinks in the first signature, but the second one is a smooth stroke from beginning to end.
There are admittedly a lot of mistakes I made and hacky shortcuts I took, but for now this is sufficient for the business needs of Rocket Lease.
The first few things I would work on are:
- Better subsetting of the recorded data or better sampling
- Variable width signatures (this is implemented very crudely, and I didn't discuss it in this post. The first signature pad in the post uses it though)
- Fix the part that renders the trailing bezier path -- Currently it actually still traces 4 point beziers which have cusps between them, then waits til the mouseup event to stroke the full path -- this is wrong, but most people don't really notice.
I blog because I like connecting with smart people.
If you are interested this or what I'm doing with online rental applications at Rocket Lease, please say hello.Say Hello To Me!