Я использую Блокнот для подписи js из szimek для создания блокнота для подписи на холсте. Я использовал 3 холста одновременно. После некоторых исследований я получил ссылку от Codepen для использования нескольких экземпляров. Это работает, хотя, но проблема возникает, когда подпись должна быть загружена. После загрузки PNG и JPG изображения становятся полностью черными. Совместное использование кодов ниже.
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>