<!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)