Capture Signature using HTML5 and iPad

IpadHtmlCanvasSvg

Ipad Problem Overview


Anyone know how this can be done? Would you use a canvas object, svg, jQuery, etc?

Ipad Solutions


Solution 1 - Ipad

Here's another canvas based version with variable width (based on drawing velocity) curves: demo at http://szimek.github.io/signature_pad and code at https://github.com/szimek/signature_pad.

signature sample

Solution 2 - Ipad

A canvas element with some JavaScript would work great.

In fact, Signature Pad (a jQuery plugin) already has this implemented.

Solution 3 - Ipad

Here is http://mcc.id.au/2010/signature.html">a quickly hacked up version of this using SVG I just did. Works well for me on my iPhone. Also works in a desktop browser using normal mouse events.

Solution 4 - Ipad

Perhaps the best two browser techs for this are Canvas, with Flash as a back up.

We tried VML on IE as backup for Canvas, but it was much slower than Flash. SVG was slower then all the rest.

With jSignature ( http://willowsystems.github.com/jSignature/ ) we used Canvas as primary, with fallback to Flash-based Canvas emulator (FlashCanvas) for IE8 and less. Id' say worked very well for us.

Solution 5 - Ipad

The options already listed are very good, however here a few more on this topic that I've researched and came across.

1) http://perfectionkills.com/exploring-canvas-drawing-techniques/<br/> 2) http://mcc.id.au/2010/signature.html<br/> 3) https://zipso.net/a-simple-touchscreen-sketchpad-using-javascript-and-html5/<br/>
And as always you may want to save the canvas to image:
http://www.html5canvastutorials.com/advanced/html5-canvas-save-drawing-as-an-image/

good luck and happy signing

Solution 6 - Ipad

@szimek (selected answer) has a well-documented solution for those who want a full-featured module with a MIT license that's good-to-go. @heycam has a simpler solution that requires no libraries or plugins, has no licenses, and can be easily customized; all of which makes it a better fit for my needs. This post tries to explain how exactly his solution works.

Basic workflow:

  1. Create a functionally blank svg to contain the signature
  2. Reserve a path element inside the container svg
  3. Use touch events (touchstart, touchmove, touchend) for the user to draw the signature using touch inputs
  4. Use mouse events (mousedown, mousemove, mouseup, mouseout) for the user to draw the signature using mouse inputs
  5. On each event, detect the type of input (touch, mouse) to get the X,Y coordinates of the path the user is drawing
  6. Append each path to the d attribute (path coordinates) of the path element so it displays to the user
  7. Add a helper function to output the signature path (path.d), which is just a string you can plug back into the path.d later on to restore the signature
  8. Add a helper function to clear the path.d value

Here's @heycam's solution as a runnable snippet:

//init
let r = document.getElementById('r'),
  p = document.getElementById('p'),
  signaturePath = '',
  isDown = false,
  svg = document.getElementById('sig_panel'),
  b_show = document.getElementById('show'),
  b_clear = document.getElementById('clear'),
  pathdata = document.getElementById('pathdata');

//drawing functions
function isTouchEvent(e) {
  return e.type.match(/^touch/);
}

function getCoords(e) {
  if (isTouchEvent(e)) {
    return e.targetTouches[0].clientX + ',' + e.targetTouches[0].clientY;
  }
  return e.clientX + ',' + e.clientY;
}

function down(e) {
  signaturePath += 'M' + getCoords(e) + ' ';
  p.setAttribute('d', signaturePath);
  isDown = true;

  if (isTouchEvent(e)) e.preventDefault();
}

function move(e) {
  if (isDown) {
    signaturePath += 'L' + getCoords(e) + ' ';
    p.setAttribute('d', signaturePath);
  }

  if (isTouchEvent(e)) e.preventDefault();
}

function up(e) {
  isDown = false;

  if (isTouchEvent(e)) e.preventDefault();
}

//input handlers
r.addEventListener('touchstart', down, false);
r.addEventListener('touchmove', move, false);
r.addEventListener('touchend', up, false);
r.addEventListener('mousedown', down, false);
r.addEventListener('mousemove', move, false);
r.addEventListener('mouseup', up, false);
r.addEventListener('mouseout', up, false);

//helper functions
function clearSignature() {
  pathdata.textContent = '';
  signaturePath = '';
  p.setAttribute('d', '');
}

function getSignature() {
  pathdata.textContent = signaturePath;
  return signaturePath;
}

//button handlers
b_show.addEventListener('click', getSignature);
b_clear.addEventListener('click', clearSignature);

svg {
  margin: .5em;
  border: 1px solid gray;
  border-radius: .5em;
}

.flex {
  display: flex;
}

button {
  margin: .5em;
}

#pathdata {
  font-family: monospace;
  background: #ddd;
  padding: 1em;
  margin: 1em .5em;
}

<svg id="sig_panel" xmlns="http://www.w3.org/2000/svg" width="300" height="100" viewBox="0 0 300 100">
  <rect id="r" width="300" height="100" fill="#ffa"/>
  <line x1="0" y1="80" x2="300" y2="80" stroke="#666" stroke-width="1" stroke-dasharray="3" shape-rendering="crispEdges" pointer-events="none"/>
  <path id="p" stroke="navy" stroke-width="2" fill="none" pointer-events="none"/>
</svg>
<div class="flex">
  <button id="show">Show signaure path data</button>
  <button id="clear">Clear signature</button>
</div>
<div id="pathdata"></div>

Saving the path.d value on the server (and client cache) is all I need. Others may need to save the entire svg itself with path.d filled in, or convert it to other formats (JPEG, PNG, PDF) using appropriate converters (not covered here).

I plan to go a step beyond and add user controls to manage the following:

  • line thickness: path.stroke-width
  • line color: path.stroke
  • line quality: path.shape-rendering

and theme the signature field (as part of my custom form lib):

  • container dimensions: rect.width, rect.height
  • container background: rect.fill
  • eliminate the "sign here" line: line

Solution 7 - Ipad

Another OpenSource signature field is https://github.com/applicius/jquery.signfield/ , registered jQuery plugin using Sketch.js .

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMark RichmanView Question on Stackoverflow
Solution 1 - IpadszimekView Answer on Stackoverflow
Solution 2 - IpadBen SView Answer on Stackoverflow
Solution 3 - IpadheycamView Answer on Stackoverflow
Solution 4 - IpadddotsenkoView Answer on Stackoverflow
Solution 5 - IpadLuigi D'AmicoView Answer on Stackoverflow
Solution 6 - IpadOXiGENView Answer on Stackoverflow
Solution 7 - IpadcchantepView Answer on Stackoverflow