代码之家  ›  专栏  ›  技术社区  ›  Hamza Zafeer Bert

2画布不能以单一HTML格式工作

  •  0
  • Hamza Zafeer Bert  · 技术社区  · 2 年前

    我正在开发一个应用程序,在这个应用程序中,单页用户必须在两个不同的画布上签署两次。下面是代码片段。

    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>

    问题

    使用上述代码画布仅在第二个框中有效,而在第一个框中无效。

    我怎样才能在两个盒子里画出不同的签名?

    0 回复  |  直到 2 年前
        1
  •  2
  •   chrwahl    2 年前

    JavaScript中的问题是,您声明了两次变量。第一 var canvas 指的是第一个canvas元素,在再次声明同一变量后有12行,现在是第二个canvas元素。所有其他(全局)变量也是如此。

    为了避免这个问题,你需要不同的变量(比如 var canvas1 = ... var canvas2 = ... )或者避免使用全局变量,因为它不可伸缩且容易混淆。这种情况下的另一种选择是将所需的变量作为属性放在画布元素本身上。例如 drawing 变量,它是每个画布元素上的属性。

    所有的回调函数( start , stop draw )有一个参数叫做 e (事件对象)。在那个物体上你可以找到 target 它总是指向canvas元素,在canvas元素上可以找到 绘画 ( e.target.drawing )这是预先定义的。同样的道理也适用于美国 prevX prevY 都是一个叫做 position .

    在回调函数中 draw() 你可以看到我找到了画布的背景( ctx ),再次基于 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>