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 元素上的 属性。

所有回调函数(startstopdraw)都有一个名为 e 的参数(事件对象)。在该对象上,您可以找到始终引用 canvas 元素的 target,而在 canvas 元素上,您可以找到 drawing (e.target.drawing)被预先定义。对于 prevXprevY 也是如此,它们都是名为 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>