A minimalist example of using Html5 Canvas to save signature as image using Web API

While working on a proposal for a project, I wanted to have a look at the possibilities of capturing the signature of client in an application (mobile, web). From the first thoughts, I was kind of doubtful about the implementation and was not really sure how easy of difficult would this be to provide as a feature which is easy to use.

I started to brainstorm with my friend Google and after searching with the few possible terms, we were in good direction. As my first thought (so 1990s), one possible option was to use some kind of 3rd part component, ActiveX etc. installed on the client which would help capturing the input. This was something I wanted to avoid at any cost. With so many different possible devices, operating systems and browser, this would not make sense at all and is call for trouble.

Another hint was to use the capability offered by Html5 Canvas. I was like, of course how could I miss this one. 😉

Check out demo here.

Canvas to capture user input

For starters, canvas element is part of HTML5 and allows for dynamic, scriptable rendering of 2D shapes and bitmap images. It is a low-level, procedural model that updates a bitmap and does not have a built-in scene graph.

So, I was going in right direction. Use canvas and somehow save this signature on the server side for further use. Well, I am not going into details but if you are storing signature of user; you might need to think if it is really necessary and other privacy issues and measures associated with it.

Capturing user input is one of the most common scenario you would see when using the canvas. Canvas is especially most powerful element in Html5 for game developers these days. Anyway, as I did not want to reinvent the wheel for capturing the signature input (well, actually nothing but a user driven drawing), I decided to use Signature Pad written by Szymon Nowak. In his own words, Signature Pad is a JavaScript library for drawing smooth signatures. Its HTML5 canvas based and uses variable width Bézier curve interpolation based on Smoother Signatures. It works in all modern desktop and mobile browsers and doesn’t depend on any external libraries.

A very basic html page I created looked something like this containing a couple of buttons plus a canvas which would be used for capturing the user signature.


<div class="page-header">
	<h1>Signature App demonstration using SignaturePad and Web API</h1>
</div>
<div class="panel panel-default">
	<div class="panel-body" id="signature-pad">
	<div></div>
	<div>
	<div class="alert alert-info">Sign above</div>
		 <button class="btn btn-info" data-action="clear">Clear</button>
		 <button class="btn btn-success" data-action="save">Save</button></div>
	</div>
</div>

toDataUrl to get canvas image as base64 encoded Url

The internals, initialization etc. are minor and are out of the box from Signature Pad and you can see in the attached sample project with this post. The next step was to save the captured signature on the canvas to the server. It turned out the canvas was awesome beyond my imagination. It offers a method called toDataURL(). It basically is a URL containing a representation of the image in the format specified by type (defaults to PNG). The returned image is 96dpi. To get the image data URL of the canvas, we can use the toDataURL() method of the canvas object which converts the canvas drawing into a 64 bit encoded PNG URL. If you’d like for the image data URL to be in the jpeg format, you can pass image/jpeg as the first argument in the toDataURL() method. If you’d like to control the image quality for a jpeg image, you can pass in a number from 0 to 1 as the second argument to the toDataURL() method.

Awesome. Isn’t it?

Web API to save image on server

I decided to get my hands dirty on Web API to implement the server-side saving as I did not try it earlier. Again for starters, a server-side web API is a programmatic interface to a defined request-response message system, typically expressed in JSON or XML, which is exposed via the web—most commonly by means of an HTTP-based web server.

I started by creating a new ASP.Net project in Visual Studio 2013 and selected Empty Project template with Web API selected.

One the project has been created, the next step is add a new controller and rename it as SignatureController. The controller would look something like this:


public class SignatureController : ApiController
{
	public IHttpActionResult Post([FromBody]Signature data)
	{
		byte[] photo = Convert.FromBase64String(data.Value);

		var dir = new DirectoryInfo(HostingEnvironment.ApplicationPhysicalPath);

		using (System.IO.FileStream fs = System.IO.File.Create(Path.Combine(dir.FullName, string.Format("Img_{0}.png", Guid.NewGuid()))))
		{
			 fs.Write(photo, 0, photo.Length);
		}

		return Ok();
	}
}

The controller takes the Signature model as the input. However, this example only has the dataUrl or value of the signature defined but you can possibly thing to extend with additional members for e.g. name of the user.

Now, let’s go back to the html page which I created to start with the SignaturePad. And extend with a jQuery call to access the web API.


dataURL = signaturePad.toDataURL().replace('data:image/png;base64,', '');
var data = JSON.stringify(
				   {
					   value: dataURL
				   });

$.ajax({
	type: "POST",
	url: "/api/signature",
	contentType: false,
	processData: false,
	data: data,
	contentType: "application/json; charset=utf-8",
	success: function (msg) {
		alert("Done!");
	},
	error: onWebServiceFailed
});

And that’s it. This is a complete minimal solution to have solution for capturing the user input till saving it as a file on server.

Conclusion:

The latest development in web technologies have opened up the opportunities to implement the functionalities in an easier manner for developers. What’s important is that we keep ourselves up-to-date with them and trust me this is a challenging part (especially for me J).

And why I called this as minimalist is because it really is. With a least amount of code, we could have a nice functionality in place. And it’s not only limited to signature capture, think about a possibility to have a same implementation on using a big screen white board and sending across the drawing to whole team with just one click of button.

Another reason for minimalist is that it took me less than 30 minutes to build this example from end to end. On the other hand, more than that in writing this blog.

Download sample project

References:

https://developer.mozilla.org/en/docs/Web/API/HTMLCanvasElement

http://www.html5canvastutorials.com/advanced/html5-canvas-get-image-data-url/

http://www.asp.net/web-api

  • coral

    Nice. Now lets all go there and give our signature electronically

  • Gerg Downs

    I think this needs a little modification: on mouse reentry the exit- and reentry-points should not be connected with a stroke.

    Other than that, looks nice, now all that’s left is to check with your local lawyer if this can be considered a legally binding signature.

    • Null Reference

      I’ve digitally signed documents like this a lot on sites offering this exact service so the medium is legit but I don’t know if the site running this service has to have… paperwork or something to legitimize their operation. I agree 100% on your first point. This seems to be a very common issue with any mouse to draw in a square apps.

  • uriel

    please advise how i can use this in a web form not api, and save to sql database

    • @Uriel, the concept would remain same.

      What you can do is perform a postback with the canvas image dataUrl to your webform. Within web form, you can read the image url and save it to SQL database or write to file etc.

      • july99

        Manas can you please provide some codes for webform save button postback event?

        So instead of

        saveButton.addEventListener(“click”, function (event) {

        if (signaturePad.isEmpty()) {

        alert(“Please provide signature first.”);

        } else {

        SaveImage(signaturePad.toDataURL());

        }

        }

        How to do get these data of image url and save it to database, what variable type needed in database, is it string (nvarchar) or vbinary etc…

  • halifaxdatageek

    Looks neat, am I the only one who’s amused that it’s called minimalist-example-using-html5-canvas-save-signature-image-using-web-api?

  • NeoTechni

    I’m having some trouble with it. The X/Y coordinates seem to be multiplied by the wrong number, so the farther you draw away from 0,0, the farther it draws to the right/down of the actual coordinates.