4

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>
Matt Ellen
  • 11,268
  • 4
  • 68
  • 90
Kevin
  • 1,241
  • 7
  • 20

1 Answers1

7

The problem is that you're not setting the background colour, so the JPG is defaulting to black, which means that the whole image is black, because it can't handle transparency.

It's not a problem for PNG or SVG, which is why these work as expected.

To fix it set the background colour of the signature pad to white (taken from the signature pad example):

var signaturePad = new SignaturePad(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)'
});

To apply the above to your code:

signaturePad1 = new SignaturePad(canvas1, {backgroundColor: 'rgb(255, 255, 255)'});
Matt Ellen
  • 11,268
  • 4
  • 68
  • 90
  • How can I add the ` backgroundColor ` to the wrapper ` var wrapper1 = document.getElementById("signature-pad-1"), canvas1 = wrapper1.querySelector("canvas"), signaturePad1; ` – Kevin Feb 19 '20 at 11:11
  • 1
    @Kevin do it where you construct the signature pad. underneath where you resize the canvas. – Matt Ellen Feb 19 '20 at 11:15
  • Could You please Edit my fiddle? I am not sure where could I add it. – Kevin Feb 19 '20 at 11:19
  • Also If i add the bgColor to the canvas how it will reflect in PNG version – Kevin Feb 19 '20 at 11:23
  • @Kevin in your code, where you write `signaturePad1 = new SignaturePad(canvas1);`, and also for the second signature pad. That's where you need to make the change. Changing the background colour will simply give the PNG and SVG a background colour. If you stick to white, you won't notice a difference. – Matt Ellen Feb 19 '20 at 11:37