2 个画布在单一 HTML 表格中不起作用
2 canvases are not working in Single HTML Form
我正在开发一个应用程序,在该应用程序中,单页用户必须在两个不同的 canvas 中签名两次。下面是代码片段。
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>
问题
使用上面的代码 canvas 仅在第二个盒子中有效,而在第一个盒子中无效。
如何在两个框内绘制不同的签名?
您 JavaScript 中的问题是您声明了两次变量。 First var canvas
指的是第一个 canvas 元素和同一变量再次声明后的 12 行,现在是第二个 canvas 元素。所有其他(全局)变量也是如此。
为避免此问题,您需要不同的变量(如 var canvas1 = ...
和 var canvas2 = ...
),或者避免使用全局变量,因为它无法缩放且容易混淆。在这种情况下,另一种方法是将您需要的变量作为 canvas 元素本身的属性。一个例子是 drawing
变量,它是每个 canvas 元素上的 属性。
所有回调函数(start
、stop
和 draw
)都有一个名为 e
的参数(事件对象)。在该对象上,您可以找到始终引用 canvas 元素的 target
,而在 canvas 元素上,您可以找到 drawing
(e.target.drawing
)被预先定义。对于 prevX
和 prevY
也是如此,它们都是名为 position
.
的对象的一部分
在回调函数 draw()
中,您可以看到我再次基于 e.target
.
找到了 canvas 上下文 (ctx
)
/*
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>
我正在开发一个应用程序,在该应用程序中,单页用户必须在两个不同的 canvas 中签名两次。下面是代码片段。
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>
问题
使用上面的代码 canvas 仅在第二个盒子中有效,而在第一个盒子中无效。
如何在两个框内绘制不同的签名?
您 JavaScript 中的问题是您声明了两次变量。 First var canvas
指的是第一个 canvas 元素和同一变量再次声明后的 12 行,现在是第二个 canvas 元素。所有其他(全局)变量也是如此。
为避免此问题,您需要不同的变量(如 var canvas1 = ...
和 var canvas2 = ...
),或者避免使用全局变量,因为它无法缩放且容易混淆。在这种情况下,另一种方法是将您需要的变量作为 canvas 元素本身的属性。一个例子是 drawing
变量,它是每个 canvas 元素上的 属性。
所有回调函数(start
、stop
和 draw
)都有一个名为 e
的参数(事件对象)。在该对象上,您可以找到始终引用 canvas 元素的 target
,而在 canvas 元素上,您可以找到 drawing
(e.target.drawing
)被预先定义。对于 prevX
和 prevY
也是如此,它们都是名为 position
.
在回调函数 draw()
中,您可以看到我再次基于 e.target
.
ctx
)
/*
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>