Blog Archive

Capture signature using HTML5 canvas - Use for iPad, iPhone, Android Tablets and Phones

With the help of HTML5 canvas its very easy to draw stuff such as lines, arcs, rectangle etc. Capturing a signature on a mobile devices such as iPads, Android Tablets and smart Phones has so many uses in our day to to day business applications. It can completely automate so many business processes such as proof of delivery, any type of form application, may be in future we can sign credit card transactions that are done online.

So here is simple application with complete source that captures a signature and then lets you save it on the server. The client side programming is done with the help of HTML5 canvas, ExtJs 4 JavaScript framework. On the server side its Java Servlet. You can replace them with any technology of your linking such as plain JavaScript or jQuery and php for server programming. You can also use this as a starting point for your own paint application.


Capture signature using HTML5 canvas, ExtJs 4 and Java Servlet
Capture signature using HTML5 canvas, ExtJs 4 and Java Servlet
Capture signature using HTML5 canvas, ExtJs 4 and Java Servlet

Please Note: I used the computer mouse to draw that Text on my browser but if you use the finger on your touch screen the text will be much more smooth.

The application runs on any browser that supports the CANVAS element introduced in the HTML5. Also you can run the application on your iPad, iPhone, Android OS based smart phones and tablets. It should run on Windows and Blackberry smart phones and tablets as the application is not OS dependent. The backbone of this application is the HTML5 canvas element and the following events ...
  • Browser Mouse events
    • mousedown
      • Fires when the user depresses the mouse button
    • mousemove
      • Fires when the user moves the mouse.
    • mouseup
      • Fires when the user releases the mouse button.
  • Browser Touch events
    • touchstart 
      • Happens every time a finger is placed on the screen
    • touchmove 
      • Happens as a finger already placed on the screen is moved across the screen
    • touchend 
      • Happens every time a finger is removed from the screen

Step 1: Create the HTML file - index.html

<!DOCTYPE html>
<html>
<head>
    <title>Signature Capture Example using HTML5 canvas</title>
    <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">
   
    <script type="text/javascript" src="extjs/ext-all-debug.js"></script>
    <script type="text/javascript" src="app.js"></script>
   
</head>
<body>
</body>
</html>

Step 2: Create the ExtJs application JavaScript file - app.js

This has two buttons, one for saving the signature and the other one just to clear the signature in case you messed up. In addition to that we have the signature capture panel.
Ext.Loader.setConfig({ 
    enabled: true 
});

Ext.application({
   
    name: 'MyApp',
   
    appFolder: 'app',
   
    controllers: [
                  'Signature'
              ],
   
      launch: function() {
          Ext.create('Ext.container.Viewport', {
             margin: 10, 
             defaults: {
                margin: 10,
             }, 
               items: [{
                      xtype: 'label',
                      html: '<b>Capture signature using using HTML5 canvas</b>'
                  },
                  
                  {
                      xtype: 'signatureCapture',
                  },
                  {
                    xtype: 'button',
                    text: 'Save Signature',
                    id: 'save',
                    disabled: true,
                  },
                  {
                    xtype: 'button',
                    text: 'Clear Signature',
                    id: 'clear'
                }]
          });
      }
   
});

Step 3: Signature Capture Panel - SignatureCapture.js

SignatureCapture panel has one child panel that contains the canvas element that we need to draw our signature.

Ext.define('MyApp.view.SignatureCapture', {
    extend: 'Ext.Container',
    alias : 'widget.signatureCapture',
   
    layout: {
        type: 'vbox',
        align: 'stretch'
    },
    width: 600,
    height: 300,
    border: 1,
    style: {borderColor:'#000000', borderStyle:'solid', borderWidth:'1px'},
   
    items: [
        {
            xtype: 'panel',
            id: 'signature',
            html: '<canvas id="signaturePanel" width="600" height="300">no canvas support</canvas>'
        }]
  
});

Step 4: Application controller file - Signature.js

This is the heart of the application where we get a reference to our canvas element and its 2d context. It takes care of saving the signature on the server with the help of an AJAX request. The image is sent to the server as a Base64 encoded string. To learn more about HTML5 canvas click on the link below ...
HTML5 canvas tutorial for beginners - getContext() toDataURL() toBlob()
Ext.define('MyApp.controller.Signature', {
    extend : 'Ext.app.Controller',
   
    //define the views
    views : ['SignatureCapture'],
    //define refs
    refs: [{
        ref: 'mySignature', 
        selector: 'panel[id="signature"]'
    }], 
   
    init : function() {
        this.control({
           
            'signatureCapture' : {
                afterrender : this.onPanelRendered
            },
            'viewport button[id=clear]' : {
                click : this.onClearSignature   
            }
            ,
            'viewport button[id=save]' : {
                click : this.onSaveSignature   
            }
        });
    },

    onClearSignature: function(button) {
        console.log('Clear Signature button clicked!');
        signPad.width = signPad.width;
        signPadContext.lineWidth = 3;
        saveButton.disable();
    },
   
    onSaveSignature: function() {
        console.log('Save Signature button clicked!');
        //Returns the content of the current canvas as an image that you can 
        //use as a source for another canvas or an HTML element 
        var data = signPad.toDataURL();
        var signatureData = data.replace(/^data:image\/(png|jpg);base64,/, "");
       
        //create an AJAX request
        Ext.Ajax.request({
            url : 'SaveSignature',
            method:'POST', 
            params : {
                'signatureData' : signatureData
            },
            scope : this,
            //method to call when the request is successful
            success : this.onSaveSuccess,
            //method to call when the request is a failure
            failure : this.onSaveFailure
        }); 
    },
     
    onPanelRendered: function(panel) {
        console.log('Signature Panel rendered, get ready to Sign!');
       
        var view = panel.up('viewport');
        saveButton = view.down('button[id=save]');
       
        //get the signature capture panel
        signPad = Ext.getDom("signaturePanel");
        if (signPad && signPad.getContext) {
            signPadContext = signPad.getContext('2d');
        }

        if (!signPad || !signPadContext) {
            alert('Error creating signature pad.');
            return;
        }
       
        signPad.width = this.getMySignature().getWidth();
        signPad.height = this.getMySignature().getHeight();
       
        //Mouse events
        signPad.addEventListener('mousedown', this.eventSignPad, false);
        signPad.addEventListener('mousemove', this.eventSignPad, false);
        signPad.addEventListener('mouseup', this.eventSignPad, false);
       
        //Touch screen events
        signPad.addEventListener('touchstart', this.eventTouchPad, false);
        signPad.addEventListener('touchmove', this.eventTouchPad, false);
        signPad.addEventListener('touchend', this.eventTouchPad, false);
       
        sign = new this.signCap();
        signPadContext.lineWidth = 3;
    },
   
    signCap: function()  {
        var sign = this;
        this.draw = false;
        this.start = false;
       
        this.mousedown = function(event) {
            signPadContext.beginPath();
            signPadContext.arc(event._x, event._y,1,0*Math.PI,2*Math.PI);
            signPadContext.fill();
            signPadContext.stroke();
            signPadContext.moveTo(event._x, event._y);
            sign.draw = true;
            saveButton.enable();
        };

        this.mousemove = function(event) {
            if (sign.draw) {
                signPadContext.lineTo(event._x, event._y);
                signPadContext.stroke();
            }
        };

        this.mouseup = function(event) {
            if (sign.draw) {
                sign.mousemove(event);
                sign.draw = false;
            }
        };
       
        this.touchstart = function(event) {
            signPadContext.beginPath();
            signPadContext.arc(event._x, event._y,1,0*Math.PI,2*Math.PI);
            signPadContext.fill();
            signPadContext.stroke();
            signPadContext.moveTo(event._x, event._y);
            sign.start = true;
            saveButton.enable();
        };

        this.touchmove = function(event) {
            event.preventDefault(); 
            if (sign.start) {
                signPadContext.lineTo(event._x, event._y);
                signPadContext.stroke();
            }
        };

        this.touchend = function(event) {
            if (sign.start) {
                sign.touchmove(event);
                sign.start = false;
            }
        };
         
    },

    eventSignPad: function(event) {
        if (event.offsetX || event.offsetX == 0) {
            event._x = event.offsetX;
            event._y = event.offsetY;
        } else if (event.layerX || event.layerX == 0) {
            event._x = event.layerX;
            event._y = event.layerY;
        }
       
        var func = sign[event.type];
        if (func) {
            func(event);
        }
  
    },
   
    eventTouchPad: function(event) {
       
        var mySign = Ext.get("signature");
        //in the case of a mouse there can only be one point of click
        //but when using a touch screen you can touch at multiple places
        //at the same time. Here we are only concerned about the first
        //touch event. Next we get the canvas element's left and Top offsets 
        //and deduct them from the current coordinates to get the position
        //relative to the canvas 0,0 (x,y) reference.
        event._x = event.targetTouches[0].pageX - mySign.getX();
        event._y = event.targetTouches[0].pageY - mySign.getY();
       
        var func = sign[event.type];
        if (func) {
            func(event);
        }
       
    },
   
    onSaveFailure : function(err) {
        //Alert the user about communication error
        Ext.MessageBox.alert('Error occured during saving the signature', 'Please try again!');
    },

    onSaveSuccess : function(response, opts) {
        //Received response from the server
        response = Ext.decode(response.responseText);
        Ext.MessageBox.alert('Save Successful', 'File name is: ' + response.fileName);
    },
   
           
});


Capture signature using HTML5 canvas, ExtJs 4 and Java Servlet

Step 5: Java Servlet for server side programming - SaveSignature.java

The Java Servlet creates an unique file name using current date and time. It uses the Base64 decoder to create a PNG image file from the image string.
package com.as400samplecode;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.gson.JsonObject;

public class SaveSignature extends HttpServlet {
   
    private static final long serialVersionUID = 1L;
    private static final String DESTINATION_DIR_PATH ="/signatureFolder";
    private File destinationDir, filePath;
   
    public SaveSignature() {
        super();
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // nothing here
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
       
        //PrintWriter to send the JSON response back
        PrintWriter out = response.getWriter();

        //set content type and header attributes
        response.setContentType("text/html");
        response.setHeader("Cache-control", "no-cache, no-store");
        response.setHeader("Pragma", "no-cache");
        response.setHeader("Expires", "-1");
       
        JsonObject myObj = new JsonObject();
       
        String signatureData = request.getParameter("signatureData");
        String realPath = getServletContext().getRealPath(DESTINATION_DIR_PATH);
        String fileName = "Signature_" + getTodaysDate() + "_" + getCurrentTime() + ".png";
       
        destinationDir = new File(realPath);
        if(!destinationDir.isDirectory()) {
            myObj.addProperty("success", false);
            myObj.addProperty("message", "Signature destination folder not found!");
        }
        else {
            filePath = new File(realPath, fileName);
            Base64.decodeToFile(signatureData, filePath.getPath());
            myObj.addProperty("success", true);
            myObj.addProperty("fileName", fileName);
        }
        out.println(myObj.toString());
        out.close();
       
    }
   
    private String getTodaysDate() { 

        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        String todaysDate = dateFormat.format(System.currentTimeMillis());
        return todaysDate;

    }

    private String getCurrentTime() {

        DateFormat dateFormat = new SimpleDateFormat("kkmmss");
        String currentTime = dateFormat.format(System.currentTimeMillis());
        return currentTime;

    }

}


50 comments :

  1. I need this code, could someone send it to me?

    ReplyDelete
  2. i need this code too
    can any one help me
    thanks

    ReplyDelete
  3. Your example does not work in Nokia Lumia 920 - Windows Phone. Can not draw a smooth curve of the line!

    ReplyDelete
    Replies
    1. Well I don't have a windows phone to Test it out.

      Delete
  4. This code is awesome and very resourceful. Would you happen to have a guide on how to implement this in more detail from the server side?

    ReplyDelete
    Replies
    1. Not sure what you mean by that. The application for the signature capture is based on HTML5 canvas and Javascript so it has to be client side programming and then it encodes the signature to be sent to the server which decodes it back and writes to a file.

      Delete
  5. this would be great if it worked in IE or Firefox, I haven't been able to get it to work in either if it's supposed to!

    ReplyDelete
  6. Is this the complete code? I've copied and created every file shown on here and can't get this to even display. The demo works fine in IE 10 but I can't get it to run on my server for nothing. I've been looking for this exact type of script for weeks and now that I find it I can't get it to work? is it possible to get the code in a zip file?

    ReplyDelete
    Replies
    1. This is the complete source code and zip files are not provided for the project as of now.

      Delete
  7. Is it safe to assume this doesn't work and there is nobody that monitors these comments and no way to connect the developer?

    ReplyDelete
    Replies
    1. It works as you can see from the demo. Also keep in mind that its javascript so there is no way that I am hiding any kind of source code here. I do my best to keep this blog to help out as much as I can but to reply every comment or solve programming issues is out question. I would recommend forums such as stackoverflow.com for that.

      Delete
  8. oops no way to contact the developer!

    ReplyDelete
  9. Come on people it's not difficult to find out for yourselves.
    See what's missing...
    type="text/javascript" src="extjs/ext-all-debug.js"

    Go to the sample page and check the resources if you can't find ExtJS anywhere else.

    Thanks for posting the code OP, saved me a lot of time!

    ReplyDelete
  10. Why can't someone just write some code on a blog and say: "Here you go, just copy this, no external B.S. libs needed!" ?

    ReplyDelete
    Replies
    1. Why don't you write it yourself! The author took his time to write this code and shared it to help all of us learn and use it for our own projects. How about you show some respect and gratitude for his hard work!

      I would like to say Thank You, with a few tweaks this is exactly what I needed for my project!

      Delete
    2. Anon. Coward (4:38 PM),

      if you don't understand why people use libraries then you shouldn't be doing software development and looking at blog's asking for a non library version.

      Delete
  11. we are, planning to do online signature verification app for android mobiles , how can we have a canvas which can accept human signature and record the results which further can be processed by some server?

    ReplyDelete
  12. Thank you very much! this helped me a lot

    ReplyDelete
  13. Thanks. I absolutely love this site. Stick with it!

    Look into my blog postrecycled,move home,tape,sellotape,furniture

    ReplyDelete
  14. Does anyone have the code for signature verification

    ReplyDelete
  15. where is the link to download the full code? ;)

    ReplyDelete
  16. where is the link to download the full code? ;)

    ReplyDelete
  17. Thanks for sharing such valuable information, this being really good to know about.

    ReplyDelete
  18. This is great! I need this code too
    can any one help me.. Thank you! :)

    ReplyDelete
  19. Looks great, but unfortunaly when I enter the canvas on an Android phone it (the canvas) turns completly black.

    ReplyDelete
  20. where is the link to download the full code? ;) I need the code plss.Thks.

    ReplyDelete
  21. Could you please share code.

    ReplyDelete
  22. if it does not work in IE then it is useless.

    ReplyDelete
  23. Thanks, works very well !! :) I have written a similar script, please have a look www.supersignature.com
    Cheers!, Andy.

    ReplyDelete
  24. Sorry i can't download but it works great.
    Please Send me this code
    thnks

    ReplyDelete
  25. Many mistake HTML as a programming language but rather its a markup language and not progaramming language. HtML5 is the latest and technically most advanced version of HTML. To know more
    html5 training in chennai|html5 training chennai|html5 course in chennai|html5 training institutes in chennai|html5 training

    ReplyDelete
  26. I appreciate the effort of the blogger. I have one small question which is related to html5. If you could help me out then it would be really helpful. How is the page structure in html5 is different from html4?
    html5 training in chennai|html5 course in chennai|html5 training institutes in chennai

    ReplyDelete
  27. Hi, actually I'am new to angularJs and infact I'am learning angularjs with online training. I'am having doubt, if you could solve the doubt for me that would be very helpful. The doubt is, how can I reset a “$timeout”, and disable a “$watch()”?
    Regards,
    angularjs training in Chennai | angularjs training | angularjs training Chennai

    ReplyDelete
  28. The programmed based data analysis is possible now by using quantitative data analysis methods. This is really nice to have.

    ReplyDelete
  29. True that HTML5 element gives you an easy and powerful way to draw graphics using JavaScript. It can be used to draw graphs, make photo compositions or do simple (and not so simple) animations. I would also draw your attention to BuddyPress plugin on WordPress. Amazing is that you can build a social community on your network and let members interact socially :)

    ReplyDelete
  30. The blog you presented was very nice and interesting which helped me to get update on the recent technologies.
    Angularjs training in chennai | Angularjs course in Chennai

    ReplyDelete
  31. To have smooth signatues try this html5 signature capture or visit supersignature.com

    ReplyDelete
  32. Well Said, you have furnished the right information that will be useful to anyone at all time. Thanks for sharing your Ideas.
    Angularjs training in chennai | Angularjs course in Chennai

    ReplyDelete
  33. Thanks for posting this useful content, Good to know about new things here, Let me share this,
    AngularJS Training in Chennai | AngularJS Training | Best AngularJS Training Institute in Chennai

    ReplyDelete

  34. The share your really gives us excitement. Thanks for your sharing. If you feel tired at work or study try to participate in our games to bring the most exciting feeling. Thank you!
    hotmail sign in | red ball | 192.168.1.1

    ReplyDelete
  35. This comment has been removed by the author.

    ReplyDelete