I am using Signature pad js from szimek for making canvas signature pad. I have used 3 canvas at a time. After some research I got a link from Codepen for using multiple instance. Its working though, but the problem arise when the signature needs to be downloaded. After download the PNG and JPG, the images get fully black. Sharing the codes below.
var wrapper1 = document.getElementById("signature-pad-1"),
canvas1 = wrapper1.querySelector("canvas"),
signaturePad1;
var wrapper2 = document.getElementById("signature-pad-2"),
canvas2 = wrapper2.querySelector("canvas"),
signaturePad2;
function resizeCanvas(canvas) {
var ratio = window.devicePixelRatio || 1;
canvas.width = canvas.offsetWidth * ratio;
canvas.height = canvas.offsetHeight * ratio;
canvas.getContext("2d").scale(ratio, ratio);
}
function clear1() { signaturePad1.clear(); }
function clear2() { signaturePad2.clear(); }
function save() {
if (signaturePad1.isEmpty() || signaturePad2.isEmpty())
alert("Error: Please sign both pads!");
else
alert("Success!");
}
resizeCanvas(canvas1);
signaturePad1 = new SignaturePad(canvas1);
resizeCanvas(canvas2);
signaturePad2 = new SignaturePad(canvas2);
$("#clear1").click(clear1);
$("#clear2").click(clear2);
$("#save").click(save);
var savePNGButton1 = wrapper1.querySelector("[data-action=save-png]");
var saveJPGButton1 = wrapper1.querySelector("[data-action=save-jpg]");
var saveSVGButton1 = wrapper1.querySelector("[data-action=save-svg]");
var savePNGButton2 = wrapper2.querySelector("[data-action=save-png]");
var saveJPGButton2 = wrapper2.querySelector("[data-action=save-jpg]");
var saveSVGButton2 = wrapper2.querySelector("[data-action=save-svg]");
// One could simply use Canvas#toBlob method instead, but it's just to show
// that it can be done using result of SignaturePad#toDataURL.
function dataURLToBlob(dataURL) {
// Code taken from https://github.com/ebidel/filer.js
var parts = dataURL.split(';base64,');
var contentType = parts[0].split(":")[1];
var raw = window.atob(parts[1]);
var rawLength = raw.length;
var uInt8Array = new Uint8Array(rawLength);
for (var i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}
function download(dataURL, filename) {
if (navigator.userAgent.indexOf("Safari") > -1 && navigator.userAgent.indexOf("Chrome") === -1) {
window.open(dataURL);
} else {
var blob = dataURLToBlob(dataURL);
var url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
a.style = "display: none";
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
}
}
savePNGButton1.addEventListener("click", function (event) {
if (signaturePad1.isEmpty()) {
alert("Please provide a signature first.");
} else {
var dataURL = signaturePad1.toDataURL();
download(dataURL, "signature.png");
}
});
saveJPGButton1.addEventListener("click", function (event) {
if (signaturePad1.isEmpty()) {
alert("Please provide a signature first.");
} else {
var dataURL = signaturePad1.toDataURL("image/jpeg");
download(dataURL, "signature.jpg");
}
});
saveSVGButton1.addEventListener("click", function (event) {
if (signaturePad1.isEmpty()) {
alert("Please provide a signature first.");
} else {
var dataURL = signaturePad1.toDataURL('image/svg+xml');
download(dataURL, "signature.svg");
}
});
savePNGButton2.addEventListener("click", function (event) {
if (signaturePad2.isEmpty()) {
alert("Please provide a signature first.");
} else {
var dataURL = signaturePad2.toDataURL();
download(dataURL, "signature.png");
}
});
saveJPGButton2.addEventListener("click", function (event) {
if (signaturePad2.isEmpty()) {
alert("Please provide a signature first.");
} else {
var dataURL = signaturePad2.toDataURL("image/jpeg");
download(dataURL, "signature.jpg");
}
});
saveSVGButton2.addEventListener("click", function (event) {
if (signaturePad2.isEmpty()) {
alert("Please provide a signature first.");
} else {
var dataURL = signaturePad2.toDataURL('image/svg+xml');
download(dataURL, "signature.svg");
}
});
body {
font-family: Helvetica, Sans-Serif;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
}
.m-signature-pad {
position: relative;
font-size: 10px;
width: 400px;
height: 400px;
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;
}
.m-signature-pad:before, .m-signature-pad:after {
position: absolute;
z-index: -1;
content: "";
width: 40%;
height: 10px;
left: 20px;
bottom: 10px;
background: transparent;
-webkit-transform: skew(-3deg) rotate(-3deg);
-moz-transform: skew(-3deg) rotate(-3deg);
-ms-transform: skew(-3deg) rotate(-3deg);
-o-transform: skew(-3deg) rotate(-3deg);
transform: skew(-3deg) rotate(-3deg);
box-shadow: 0 8px 12px rgba(0, 0, 0, 0.4);
}
.m-signature-pad:after {
left: auto;
right: 20px;
-webkit-transform: skew(3deg) rotate(3deg);
-moz-transform: skew(3deg) rotate(3deg);
-ms-transform: skew(3deg) rotate(3deg);
-o-transform: skew(3deg) rotate(3deg);
transform: skew(3deg) rotate(3deg);
}
.m-signature-pad--body {
position: absolute;
left: 20px;
right: 20px;
top: 20px;
bottom: 20px;
border: 1px solid #f4f4f4;
}
.m-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;
background-color: #fff;
}
.btn-grp{display:block; width:100%;}
.signature-pad--footer{position:absolute; bottom:0; left:0; right:0;}
@media screen and (max-width: 1024px) {
.m-signature-pad {
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 50%;
height: auto;
min-width: 100px;
min-height: 100px;
margin: 5%;
}
#github {
display: none;
}
}
@media screen and (min-device-width: 768px) and (max-device-width: 1024px) {
.m-signature-pad {
margin: 10%;
}
}
@media screen and (max-height: 320px) {
.m-signature-pad--body {
left: 0;
right: 0;
top: 0;
bottom: 32px;
}
.m-signature-pad--footer {
left: 20px;
right: 20px;
bottom: 4px;
height: 28px;
}
.m-signature-pad--footer
.description {
font-size: 1em;
margin-top: 1em;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/signature_pad/1.3.2/signature_pad.min.js"></script>
<div id="signature-pad-1" class="m-signature-pad">
<div class="m-signature-pad--body">
<canvas></canvas>
</div>
<div class="signature-pad--footer">
<div class="signature-pad--actions">
<div>
<button type="button" class="button clear" data-action="clear">Clear</button>
<button type="button" class="button" data-action="change-color">Change color</button>
<button type="button" class="button" data-action="undo">Undo</button>
</div>
<div>
<button type="button" class="button save" data-action="save-png">Save as PNG</button>
<button type="button" class="button save" data-action="save-jpg">Save as JPG</button>
<button type="button" class="button save" data-action="save-svg">Save as SVG</button>
</div>
</div>
</div>
</div>
<button id="clear1" onclick="clear(1);">Clear</button>
<div id="signature-pad-2" class="m-signature-pad">
<div class="m-signature-pad--body">
<canvas></canvas>
</div>
<div class="signature-pad--footer">
<div class="signature-pad--actions">
<div>
<button type="button" class="button clear" data-action="clear">Clear</button>
<button type="button" class="button" data-action="change-color">Change color</button>
<button type="button" class="button" data-action="undo">Undo</button>
</div>
<div>
<button type="button" class="button save" data-action="save-png">Save as PNG</button>
<button type="button" class="button save" data-action="save-jpg">Save as JPG</button>
<button type="button" class="button save" data-action="save-svg">Save as SVG</button>
</div>
</div>
</div>
</div>
<button id="clear2" onclick="clear(2);">Clear</button>
<br />
<button id="save">Save</button>