I have a form that needs to be signed by three people. I initially set it up to be signed by one person, but found out I needed three. I can't get all three to work.
Canvas Containers:
<div class="rowElem">
<div id="container2">
</div>
</div>
<div class="rowElem">
<div id="container3">
</div>
</div>
<div class="rowElem">
<div id="container4">
</div>
</div>
Javascript:
<script>
(function (ns) {
"use strict";
ns.SignatureControl = function (options) {
var containerId = options && options.canvasId || "container2",
callback = options && options.callback || {},
label = options && options.label || "Teacher Signature",
cWidth = options && options.width || "300px",
cHeight = options && options.height || "300px",
btnClearId,
canvas,
ctx;
function initCotnrol() {
createControlElements();
wireButtonEvents();
canvas = _("signatureCanvas");
canvas.addEventListener("mousedown", pointerDown, false);
canvas.addEventListener("mouseup", pointerUp, false);
ctx = canvas.getContext("2d");
}
function createControlElements() {
var signatureArea = document.createElement("div"),
labelDiv = document.createElement("div"),
canvasDiv = document.createElement("div"),
canvasElement = document.createElement("canvas"),
buttonsContainer = document.createElement("div"),
buttonClear = document.createElement("button");
labelDiv.className = "signatureLabel";
labelDiv.textContent = label;
canvasElement.id = "signatureCanvas";
canvasElement.clientWidth = cWidth;
canvasElement.clientHeight = cHeight;
canvasElement.style.border = "solid 2px black";
canvasElement.style.background = "white";
buttonClear.id = "btnClear";
buttonClear.textContent = "Clear Signature Panel";
canvasDiv.appendChild(canvasElement);
buttonsContainer.appendChild(buttonClear);
signatureArea.className = "signatureArea";
signatureArea.appendChild(labelDiv);
signatureArea.appendChild(canvasDiv);
signatureArea.appendChild(buttonsContainer);
_(containerId).appendChild(signatureArea);
}
function pointerDown(evt) {
ctx.beginPath();
ctx.moveTo(evt.offsetX, evt.offsetY);
canvas.addEventListener("mousemove", paint, false);
}
function pointerUp(evt) {
canvas.removeEventListener("mousemove", paint);
paint(evt);
}
function paint(evt) {
ctx.lineTo(evt.offsetX, evt.offsetY);
ctx.stroke();
}
function wireButtonEvents() {
var btnClear = _("btnClear");
btnClear.addEventListener("click", function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}, false);
}
function getSignatureImage() {
return ctx.getImageData(0, 0, canvas.width, canvas.height).data;
}
return {
init: initCotnrol,
getSignatureImage: getSignatureImage
};
}
})(this.ns = this.ns || {});
This is the initiator script:
function teacherSig() {
var signature = new ns.SignatureControl({ containerId: 'container2', callback: function () {
}
});
signature.init();
_('btnClear').className = "greyishBtn";
}
window.addEventListener('DOMContentLoaded', teacherSig, false);
</script>
The "_" are a variable set in another file for document.getElementById - I already know that works, I'm using it in all my js files.
I tried duplicating the initiator script and changing the function name/element names, but it did not do any good.
Any help would be greatly appreciated.
If anyone knows a better way to do this, I can try that as well. I'm running out of time on this project, and this was something the client added on in the end. If anyone knows another solution, a plugin or anything for multiple, I'm open to that as well.
As you ask for a better way to do it I would like suggest you use easyCanvasJS for this which setups up most of the non-trivial things but allow you to use context and canvas as usual.
For three signature boxes all you need to do is the following (keeping your original HTML code as shown in the post:
/// setup three canvases referencing parent Id and setting size:
var ez1 = new easyCanvas('container2', 350, 100),
ez2 = new easyCanvas('container3', 350, 100),
ez3 = new easyCanvas('container4', 350, 100);
/// common handler when mouse is held down, this = current easyCanvas instance
ez1.onmousemove = ez2.onmousemove = ez3.onmousemove = function(x, y) {
/// instead of this.ctx.moveTo etc.. :
this.strokeLine(this.prevX, this.prevY, x, y);
}
Now you have three boxes where you can sign into. The strokeLine
is a short hand function for drawing a line, prevX/Y
are stored internally on the easyCanvas
instance and x
and y
is already corrected relative to canvas.
(To access the canvas you would just reference ez.canvas
and for context ez.ctx
or ez.context
).
For demo's sake I threw in some save buttons in the HTML to allow you to save the canvas as an image:
save1.addEventListener('click', function(){download(ez1,1)}, false);
save2.addEventListener('click', function(){download(ez2,2)}, false);
save3.addEventListener('click', function(){download(ez3,3)}, false);
function download(ez, index) {
/// show a save dialog with filename to save image here as png
ez.download('Signature' + index + '.png');
}
If you instead need the data internally you could do this:
ez.canvas.toDataURL();
instead for each of the instances.
Update - for example: on a single save button do:
function saveSignatures() {
var sig1 = ez1.canvas.toDataURL();
var sig2 = ez2.canvas.toDataURL();
var sig3 = ez3.canvas.toDataURL();
saveByAjax(sig1, sig2, sig3); // some ajax function to save the data
}
Disclaimer: easyCanvas for JavaScript is made by myself, is free and licensed under GPL-3.0.