<!doctype html>
<html lang="en" ng-app="signIt">
<head>
    <title>AngularJs Signature Demo</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.css" />
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://code.angularjs.org/1.3.0-rc.2/angular.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
    <script src="app.js"></script>
</head>
<body ng-controller="SignCtrl" ng-init="init()">
    <div class="navbar navbar-inverse" role="navigation">
        <div class="container">
            <div class="navbar-header">
                <a class="navbar-brand" href="#">AngulaJs SignIt Demo - Open in fullscreen for better user experience</a>
            </div>
        </div>
    </div>
    <div class="container" ng-controller="SignCtrl">
        <div class="row">
            <div class="jumbotron">
                <p>This is an example petition.</p>
                <p>The following petitioners want to play a little with this demo and try to draw their signature.</p>
                <p>All the signatures will not be stored. Feel free to fork this snippet and improve the functionality ;)</p>
            </div>
        </div>
        <div class="row>">
            <div class="panel panel-default">
                <div class="panel-heading">Test to sign the petition</div>
                <div class="panel-body">
                    <form name="signForm" novalidate>
                        <div class="col-md-4">
                            <div class="form-group" validate-form>
                                <label>First Name</label>
                                <input type="text" name="fname" class="form-control" data-ng-model="newSignature.FirstName" required />
                            </div>
                        </div>
                        <div class="col-md-4">
                            <div class="form-group" validate-form>
                                <label>Last Name</label>
                                <input type="text" name="lname" class="form-control" data-ng-model="newSignature.LastName" required />
                            </div>
                        </div>
                        <div class="col-md-4">
                            <div class="form-group" validate-form>
                                <label>Email</label>
                                <input type="email" name="email" class="form-control" data-ng-model="newSignature.Email" required />
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-md-4">
                                <div class="form-group">
                                    <label>Draw your signature</label>
                                    <canvas class style="border:1px solid #000000; border-radius:5px;" width="350" height="50" id="canvas" drawing ></canvas>
                                </div>
                            </div>
                        </div>
                        <div class="row">
                            <div class="col-md-4">
                                <button class="btn btn-default" data-ng-click="clear()">Clear</button>
                                <button class="btn btn-primary" data-ng-click="addSign(newSignature)" ng-disabled="!signForm.$valid">Sign It!</button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>


        <div class="row>">
            <div class="col-md-12">
                <div class="row">
                    <h2>Signatories</h2>
                </div>
                <br />
                <div class="row">
                    <table class="table">
                        <thead>
                            <tr>
                                <th>#</th>
                                <th>First Name</th>
                                <th>Last Name</th>
                                <th>E-mail</th>
                                <th>Signature</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr data-ng-repeat="signature in signatures">
                                <th>{{$index+1}}</th>
                                <td>{{signature.FirstName}}</td>
                                <td>{{signature.LastName}}</td>
                                <td>{{signature.Email}}</td>
                                <td>
                                    <canvas class style="border:1px solid #000000; border-radius:5px;" width="350" height="50" id="canvas2" redraw data-index="{{$index}}"></canvas>
                                </td>
                            </tr>
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
var app = angular.module("signIt", ["signIt"]);

app.controller("SignCtrl", function ($scope) {
    $scope.init = function () {
        $scope.newSignature = {};
        $scope.signatures = [];

        $scope.moveToList = [];
        $scope.lineToList = [];

    };
    
    $scope.addSign = function (newSignature) {
        newSignature.Sign = { "moveToList": $scope.moveToList, "lineToList": $scope.lineToList };
        $scope.signatures.push(newSignature);
        $scope.newSignature = {};
        $scope.clear();
    };

    $scope.clear = function () {
        var canvas = document.getElementById('canvas');
        var context = canvas.getContext('2d');
        context.clearRect(0, 0, 350, 50);
        $scope.moveToList = [];
        $scope.lineToList = [];
        $scope.newSignature = {};
    };

});

app.directive("drawing", function () {
    return {
        restrict: "A",
        link: function (scope, element) {
            var ctx = element[0].getContext('2d');

            var drawing = false;

            var lastX;
            var lastY;

            element.bind('mousedown', function (event) {
                if (event.offsetX !== undefined) {
                    lastX = event.offsetX;
                    lastY = event.offsetY;
                } else {
                    lastX = event.layerX - event.currentTarget.offsetLeft;
                    lastY = event.layerY - event.currentTarget.offsetTop;
                }

                ctx.beginPath();

                drawing = true;
            });
            element.bind('mousemove', function (event) {
                if (drawing) {

                    if (event.offsetX !== undefined) {
                        currentX = event.offsetX;
                        currentY = event.offsetY;
                    } else {
                        currentX = event.layerX - event.currentTarget.offsetLeft;
                        currentY = event.layerY - event.currentTarget.offsetTop;
                    }

                    draw(lastX, lastY, currentX, currentY);

                    lastX = currentX;
                    lastY = currentY;
                }

            });
            element.bind('mouseup', function (event) {
                drawing = false;
            });

            function draw(lX, lY, cX, cY) {

                ctx.moveTo(lX, lY);

                ctx.lineTo(cX, cY);

                ctx.strokeStyle = "#4bf";

                ctx.stroke();

                var objMoveTo;
                var objLineTo;

                objMoveTo = { "lx": lX, "ly": lY };
                objLineTo = { "cx": cX, "cy": cY };

                scope.moveToList.push(objMoveTo);
                scope.lineToList.push(objLineTo);
            }



        }
    };
});

app.directive("redraw", function () {
    return {
        restrict: "A",
        link: function (scope, element, attrs) {
            var ctx = element[0].getContext('2d');

            ctx.beginPath();

            var indexSign = attrs.index;

            for (var i = 0; i < scope.signatures[indexSign].Sign.moveToList.length; i++) {
                draw(scope.signatures[indexSign].Sign.moveToList[i].lx, scope.signatures[indexSign].Sign.moveToList[i].ly, scope.signatures[indexSign].Sign.lineToList[i].cx, scope.signatures[indexSign].Sign.lineToList[i].cy);
            }

            function draw(lX, lY, cX, cY) {

                ctx.moveTo(lX, lY);

                ctx.lineTo(cX, cY);

                ctx.strokeStyle = "#4bf";

                ctx.stroke();
            }
        }
    };
});

app.directive("validateForm", function () {
    return {
        restrict: 'A',
        require: '^form',
        link: function (scope, el, attrs, formCtrl) {
            var inputEl = el[0].querySelector("[name]");
            var inputNgEl = angular.element(inputEl);
            var inputName = inputNgEl.attr('name');

            inputNgEl.on('change', function () {
                el.toggleClass('has-error', formCtrl[inputName].$invalid && formCtrl[inputName].$dirty);
            }
            );
        }
    }
});
#Signature Demo using AngularJS and Canvas

Author: Giuseppe Pace

Follow me [@giuseppepace89]([https://twitter.com/giuseppepace89)