Create an HTML form with Digital / Electronic Signature using php
Asked Answered
E

2

13

I'm looking for a solution to add a signature to a form. One where someone can sign with their mouse or with their finger on a touch device. I'm wondering if I can use something like jSignature https://willowsystems.github.io/jSignature/#/about/ to create an image, the process the form with php and create a PDF and then add the image to the PDF.

I've researched a bit and haven't found a clear solution for this. Basically I'm wanting to create a simple freelancer website contract that clients would sign online.

Estep answered 21/3, 2017 at 18:42 Comment(4)
it looks like the library you linked allows for output of base64 Image. So you could have a javascript submit button that would export the image and and set that value to a <input type="hidden" name="signature-image" /> and then have the form post with javascript.Sabo
Thanks, that's along the lines of what I was thinking. It looks like signatureconfirm.com is using jSignature in a way that I'm asking about.Estep
glad I could point you in the right directionSabo
Please keep in mind: maybe you can save an image that looks like a written signature, it may even be written by hand, just like the original, but that does not need to mean that it fulfills your country’s legal requirements. Most contracts are form-free, but when in dispute, you want to be able to demonstrate that undoubtedly person X entered a contract..Timberhead
A
31

I've created a fairly minimum prototype that uses the <canvas> element to allow signature drawings. This drawing is then added to the form as a base64 url.

Short explanation of the code:

  • Create a <canvas> element
  • Define events for mousedown (pencil down), mousemove (continue drawing) and mouseup (pencil up)
  • Draw on the canvas by creating a line between the previous and current coordinates. Note that if you would draw a lot of dots on the current coordinate, you will not get a smooth line when moving fast with your mouse.
  • When you stop drawing, we get the canvas contents as an image using canvas.toDataUrl(). This is then set on a hidden input on the form.

var canvas = document.getElementById('signature');
var ctx = canvas.getContext("2d");
var drawing = false;
var prevX, prevY;
var currX, currY;
var signature = document.getElementsByName('signature')[0];

canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mouseup", stop);
canvas.addEventListener("mousedown", start);

function start(e) {
  drawing = true;
}

function stop() {
  drawing = false;
  prevX = prevY = null;
  signature.value = canvas.toDataURL();
}

function draw(e) {
  if (!drawing) {
    return;
  }
  // Test for touchmove event, this requires another property.
  var clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
  var clientY = e.type === 'touchmove' ? e.touches[0].clientY : e.clientY;
  currX = clientX - canvas.offsetLeft;
  currY = clientY - canvas.offsetTop;
  if (!prevX && !prevY) {
    prevX = currX;
    prevY = currY;
  }

  ctx.beginPath();
  ctx.moveTo(prevX, prevY);
  ctx.lineTo(currX, currY);
  ctx.strokeStyle = 'black';
  ctx.lineWidth = 2;
  ctx.stroke();
  ctx.closePath();

  prevX = currX;
  prevY = currY;
}

function onSubmit(e) {
  console.log({
    'name': document.getElementsByName('name')[0].value,
    'signature': signature.value,
  });
  return false;
}
canvas#signature {
  border: 2px solid black;
}

form>* {
  margin: 10px;
}
<form action="submit.php" onsubmit="return onSubmit(this)" method="post">
  <div>
    <input name="name" placeholder="Your name" required />
  </div>
  <div>
    <canvas id="signature" width="300" height="100"></canvas>
  </div>
  <div>
    <input type="hidden" name="signature" />
  </div>
  <button type="submit">Send</button>
  <form>

On the PHP side, you should then be able to decode that base64 string and save it to a file like this:

$img = $_POST['signature'];
$data = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $img));
file_put_contents('storage/signature.png', $data);

Note for mobile touch events

If you need mobile/touch capability, simply change the events to:

  • mousemove : touchmove
  • mouseup : touchend
  • mousedown : touchstart

If you need both mobile and mouse inputs, you can duplicate the 3 addEventListener lines so all 6 events are tracked.

Airstrip answered 30/3, 2020 at 18:15 Comment(7)
Dude this is awesome, thanks for sharing this! Simple and doesn't require some huge js library or anything. Also nice starcraft profile pic!Bruis
This is cool! The only thing is how to make it work on mobile browser?Gynecic
@Gynecic how do you mean? It should work out of the box.Airstrip
@Airstrip it does not draw on mobile :( but works on desktopGynecic
@Gynecic oh you're right, you probably need to change the mouse events to touch events. Not sure if it will work out of the box once that's changedAirstrip
Is it possible to make this work on touch devices such as iPhone or iPad?Estep
Great solution, to make it work even if the canvas is not in the top view of the page, I'll changed offset calculation to this: var rect = canvas.getBoundingClientRect(); currX = clientX - rect.left; currY = clientY - rect.top;Skvorak
A
-3

Tnx so much! Instead of canvas.offsetLeft and offsetTop I corrected the offset by;

        var rect = canvas.getBoundingClientRect();
        var xoff = rect.left;
        var yoff = rect.top; 
Arenicolous answered 23/1, 2023 at 15:12 Comment(2)
Please share more details. How does your code relate to the initial problem?Computation
If this is a comment to a solution provided by Flame, you should place it Flame's comment section of their answer. You have posted an answer to the OP that provides no complete answer.Sweatband

© 2022 - 2024 — McMap. All rights reserved.