179

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

Mark Richman
  • 28,948
  • 25
  • 99
  • 159

7 Answers7

349

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

Community
  • 1
  • 1
szimek
  • 6,404
  • 5
  • 32
  • 36
  • 2
    Thanks in advance, best js signature lib I ever seen. Don't know why this answer just had 3 votes. https://github.com/szimek/signature_pad – VAdaihiep Aug 02 '13 at 10:17
  • 4
    I like that this does not rely on other js libraries and how well it looks. One note about using it which helped me: add a border to the canvas so you can see how it is being adjusted. Also note that css changes to the canvas do some crazy things, so just specify a height and width in the canvas element if this get out of control. – Brian McGinity Aug 17 '13 at 04:25
  • Lack of documentation isn't helpful, but the demo page lays it all out pretty clearly. I am working on storing it in the database and retrieving. This is a REALLY slick library. Thanks szimek! – Jake Sep 04 '13 at 05:43
  • 7
    Jake, what exactly is missing in your opinion in the documentation provided in README file? I'm open to suggestions how to improve it. – szimek Sep 04 '13 at 12:00
  • 12
    I apologize. I think your documentation is actually adequate. It seemed limited until I realized just how easy this is to use. I got it fully implemented in a form, storing in the database and retrieving back to page in under an hour. I suppose, I was comparing it to libraries that were much more complex to use like the chosen answer above. I hadn't worked with data URIs before, but it is a truly brilliant way to handle the storage of the data. So, I just had to acclimate myself to those and then storing and retrieving in the database was so... easy... wow. Thanks again! – Jake Sep 04 '13 at 16:18
  • 1
    No need to apologize :) I'm glad you like it. I'll probably add some info or at least a link to the wiki page about handling data URIs on the server side. Cheers! – szimek Sep 05 '13 at 07:31
  • szimek, your signature pad library works wonderfully, was exactly what I was looking for and is very easy to use. Thank you! – h-bomb Feb 07 '14 at 05:19
  • i was not able to somehow disable scroll for ios somehow but this plugin works like charm! Recomended – poorva Feb 20 '14 at 12:51
  • I'm having a few problems with the signature pad plugin, I think it's mainly due to the fact I've removed all the absolute positioning (the signature pad is part of a page, not a page on it's own like in the demo). Been hacking away but it's quite frustrating. – martincarlin87 Mar 28 '14 at 09:26
  • @martincarlin87 Are you talking about desktop or mobile? – szimek Mar 28 '14 at 12:25
  • @szimek Just testing on desktop for now. Couldn't get it to work for some reason. – martincarlin87 Mar 28 '14 at 12:59
  • Sorry it took so long for me to accept this answer. I abandoned the project a few years ago. – Mark Richman Jun 02 '14 at 15:59
  • @szimek I need 2 signatures in a same page, how do I do it? – Ronaldinho Learn Coding Sep 15 '15 at 14:30
  • @szimek How to change pen color to red? – Ronaldinho Learn Coding Sep 17 '15 at 17:50
  • 2
    @RonaldinhoLearnCoding check out the README file - there's a list of all possible options. The one you're looking for is called "penColor". – szimek Sep 18 '15 at 08:42
  • @szimek Thank you very much for a wonderful plugin and an intuitive support! – Ronaldinho Learn Coding Sep 18 '15 at 13:47
62

A canvas element with some JavaScript would work great.

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

rofrol
  • 14,438
  • 7
  • 79
  • 77
Ben S
  • 68,394
  • 30
  • 171
  • 212
  • 2
    I am astonished how beautiful this plugin is. – Gourneau Mar 14 '12 at 06:49
  • I found this plugin really hard to use unforutnately. All the demos were very specific and tricky to apply. Definitely like the other signature pad approach better: http://stackoverflow.com/a/17200715/76672 With pretty much no documentation, I was able to get it working... – Jake Sep 04 '13 at 05:46
20

Here is 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.

heycam
  • 2,188
  • 15
  • 19
12

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.

ddotsenko
  • 4,926
  • 25
  • 24
2

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/
2) http://mcc.id.au/2010/signature.html
3) https://zipso.net/a-simple-touchscreen-sketchpad-using-javascript-and-html5/

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

Luigi D'Amico
  • 665
  • 7
  • 11
1

@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
OXiGEN
  • 2,041
  • 25
  • 19
0

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

cchantep
  • 9,118
  • 3
  • 30
  • 41