AngularJS Example:
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/signature_pad/1.5.3/signature_pad.min.js"></script>
<div ng-app ng-controller="LoginController">
<div id="signaturePopup" class="modal erpModal fade" role="dialog" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog">
<!-- Modal content-->
<form name="signForm" class="erpForm" ng-submit="" novalidate>
<div class="modal-content">
<div class="modal-header greyBg">
<button type="button" class="close" ng-click="" data-dismiss="modal">×</button>
<h4 class="modal-title" style="font-weight: bold;">Sign Document</h4>
</div>
<div class="modal-body longModal">
<!-- Signature Acceptance section -->
<div ng-if="!documentPreviewEnabled" class="padd15">
<ul class="signatureTabs nav nav-tabs">
<li class="active"><a class="signatureTab" data-toggle="tab" data-target="#typeSign" role="tab" data-toggle="tab">Type</a></li>
<li><a class="signatureTab" data-toggle="tab" data-target="#drawSign" role="tab" data-toggle="tab">Draw</a></li>
<li><a class="signatureTab" data-toggle="tab" data-target="#menu2" role="tab" data-toggle="tab">Upload</a></li>
</ul>
<div class="tab-content">
<div id="typeSign" class="tab-pane fade in active">
Type section
</div>
<div id="drawSign" class="tab-pane fade">
<h3>Menu 1</h3>
<div id="signature-pad" class="signature-pad">
<div class="signature-pad--body">
...
CSS
.signature-pad {
position: relative;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
-ms-flex-direction: column;
flex-direction: column;
font-size: 10px;
width: 100%;
height: 100%;
max-width: 700px;
max-height: 460px;
border: 1px solid #e8e8e8;
background-color: #fff;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.08) inset;
border-radius: 4px;
padding: 16px;
}
.signature-pad::before,
.signature-pad::after {
position: absolute;
z-index: -1;
content: "";
width: 40%;
height: 10px;
bottom: 10px;
background: transparent;
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.4);
}
.signature-pad::before {
left: 20px;
-webkit-transform: skew(-3deg) rotate(-3deg);
transform: skew(-3deg) rotate(-3deg);
}
.signature-pad::after {
right: 20px;
-webkit-transform: skew(3deg) rotate(3deg);
transform: skew(3deg) rotate(3deg);
}
.signature-pad--body {
position: relative;
-webkit-box-flex: 1;
-ms-flex: 1;
flex: 1;
border: 1px solid #f4f4f4;
}
.signature-pad--body
canvas {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
border-radius: 4px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.02) inset;
}
.signature-pad--footer {
color: #C3C3C3;
text-align: center;
font-size: 1.2em;
margin-top: 8px;
}
.signature-pad--actions {
display: -webkit-box;
display: -ms-flexbox;
display: flex;
-webkit-box-pack: justify;
-ms-flex-pack: justify;
justify-content: space-between;
margin-top: 8px;
}
JavaScript
function LoginController($scope) {
$scope.showSignaturePopup = (documentData) => {
$("#signaturePopup").modal("show");
$scope.signatureName = '';
$scope.signatureFont = '';
$scope.documentData = documentData;
$scope.documentPreviewEnabled = true;
$scope.wrapper = document.getElementById("signature-pad");
$scope.canvas = $scope.wrapper.querySelector("canvas");
$scope.signaturePad = new SignaturePad($scope.canvas, {
// It's Necessary to use an opaque color when saving image as JPEG;
// this option can be omitted if only saving as PNG or SVG
backgroundColor: 'rgb(255, 255, 255)'
});
// console.log('$scope.signaturePad, $scope.canvas -------> ', $scope.signaturePad, $scope.canvas);
window.onresize = $scope.resizeCanvas;
$scope.resizeCanvas();
}
$scope.resizeCanvas = () => {
// When zoomed out to less than 100%, for some very strange reason,
// some browsers report devicePixelRatio as less than 1
// and only part of the canvas is cleared then.
$scope.ratio = Math.max(window.devicePixelRatio || 1, 1);
// This part causes the canvas to be cleared
$scope.canvas.width = $scope.canvas.offsetWidth * $scope.ratio;
$scope.canvas.height = $scope.canvas.offsetHeight * $scope.ratio;
$scope.canvas.getContext("2d").scale($scope.ratio, $scope.ratio);
console.log('$scope.canvas.width, $scope.canvas.height -------> ', $scope.canvas.width, $scope.canvas.height);
console.log('$scope.canvas.offsetWidth, $scope.canvas.offsetHeight -------> ', $scope.canvas.offsetWidth, $scope.canvas.offsetHeight);
console.log('$scope.ratio -------> ', $scope.ratio);
// This library does not listen for canvas changes, so after the canvas is automatically
// cleared by the browser, SignaturePad#isEmpty might still return false, even though the
// canvas looks empty, because the internal data of this library wasn't cleared. To make sure
// that the state of this library is consistent with visual state of the canvas, you
// have to...