I am working on application where on single page user have to sign two time in two different canvas. Below is the Code Snippet.
var canvas = document.getElementById('signature');
var ctx = canvas.getContext("2d");
var drawing = false;
var prevX, prevY;
var currX, currY;
var signature = document.getElementsByName('signature')[0];
canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mouseup", stop);
canvas.addEventListener("mousedown", start);
var canvas = document.getElementById('signature2');
var ctx = canvas.getContext("2d");
var drawing = false;
var prevX, prevY;
var currX, currY;
var signature2 = document.getElementsByName('signature2')[0];
canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mouseup", stop);
canvas.addEventListener("mousedown", start);
function start(e) {
drawing = true;
}
function stop() {
drawing = false;
prevX = prevY = null;
signature.value = canvas.toDataURL();
}
function draw(e) {
if (!drawing) {
return;
}
// Test for touchmove event, this requires another property.
var clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
var clientY = e.type === 'touchmove' ? e.touches[0].clientY : e.clientY;
currX = clientX - canvas.offsetLeft;
currY = clientY - canvas.offsetTop;
if (!prevX && !prevY) {
prevX = currX;
prevY = currY;
}
ctx.beginPath();
ctx.moveTo(prevX, prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.stroke();
ctx.closePath();
prevX = currX;
prevY = currY;
}
canvas#signature {
border: 2px solid black;
}
canvas#signature2 {
border: 2px solid black;
}
form>* {
margin: 10px;
}
<form method="post">
<input type="hidden" name="command" value="submit">
<div>
<input name="name" placeholder="Your name" />
</div>
<div>
<canvas id="signature" width="300" height="100"></canvas>
</div>
<div>
<input type="hidden" name="signature" />
</div>
<div>
<canvas id="signature2" width="300" height="100"></canvas>
</div>
<div>
<input type="hidden" name="signature2" />
</div>
<input type="submit" value="submit">
<form>
Problem
Using above code canvas is only working in 2nd box, while in first box it is not working.
How can i draw in both boxes different signature ?
The problem in your JavaScript is that you declare the variables twice. First var canvas
is referring to the first canvas element and 12 lines after the same variable is declared again, now with the second canvas element. And the same goes for all the other (global) variables.
To avoid this issue you need either different variables (like var canvas1 = ...
and var canvas2 = ...
) OR you avoid using global variables because it does not scale and it is confusing. An alternative in this situation is to put variables that you need as properties on the canvas element itself. An example is the drawing
variable that is a property on each canvas element.
All the callback functions (start
, stop
and draw
) have a parameter called e
(the event object). On that object you can find the target
that always refers to the canvas element, And on the canvas element you can find the drawing
(e.target.drawing
) that was defined up front. The same is true for the prevX
and prevY
that are both part of an object called position
.
In the callback function draw()
you can see that I find the canvas context (ctx
), again based on the e.target
.
/*
find all the relavant canvas elements
and call forEach to loop through the array
*/
document.querySelectorAll('form canvas').forEach(canvas => {
// properties for the canvas element
canvas.drawing = false;
canvas.position = {
prevX: undefined,
prevY: undefined
};
// mouse event listeners on the canvas element
canvas.addEventListener("mousemove", draw);
canvas.addEventListener("mouseup", stop);
canvas.addEventListener("mousedown", start);
// touch event listeners on the canvas element
canvas.addEventListener("touchmove", draw);
canvas.addEventListener("touchend", stop);
canvas.addEventListener("touchstart", start);
});
function start(e) {
e.target.drawing = true;
}
function stop(e) {
let canvas = e.target;
canvas.drawing = false;
canvas.position.prevX = canvas.position.prevY = null;
let id = canvas.id;
document.forms.form01[id].value = canvas.toDataURL();
}
function draw(e) {
let canvas = e.target;
let ctx = canvas.getContext("2d");
if (!canvas.drawing) {
return;
}
// Test for touchmove event, this requires another property.
let clientX = e.type === 'touchmove' ? e.touches[0].clientX : e.clientX;
let clientY = e.type === 'touchmove' ? e.touches[0].clientY : e.clientY;
let currX = clientX - canvas.offsetLeft;
let currY = clientY - canvas.offsetTop;
if (!canvas.position.prevX && !canvas.position.prevY) {
canvas.position.prevX = currX;
canvas.position.prevY = currY;
}
ctx.beginPath();
ctx.moveTo(canvas.position.prevX, canvas.position.prevY);
ctx.lineTo(currX, currY);
ctx.strokeStyle = 'black';
ctx.lineWidth = 2;
ctx.stroke();
ctx.closePath();
canvas.position.prevX = currX;
canvas.position.prevY = currY;
}
body {
/* can be added to prevent the page from scrolling when drawing on a mobile device */
/*overflow: hidden;*/
}
canvas#signature {
border: 2px solid black;
}
canvas#signature2 {
border: 2px solid black;
}
form>* {
margin: 10px;
}
<html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no" />
</head>
<body>
<form name="form01" method="post">
<input type="hidden" name="command" value="submit">
<div>
<input name="name" placeholder="Your name" />
</div>
<div>
<canvas id="signature" width="300" height="100"></canvas>
</div>
<div>
<input type="hidden" name="signature" />
</div>
<div>
<canvas id="signature2" width="300" height="100"></canvas>
</div>
<div>
<input type="hidden" name="signature2" />
</div>
<input type="submit" value="submit">
</form>
</body>
</html>