2 холста не работают в одиночной HTML-форме

Я работаю над приложением, в котором на одной странице пользователь должен подписывать два раза на двух разных холстах. Ниже приведен фрагмент кода.

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 работает только во втором поле, а в первом - не работает.

Как я могу нарисовать в обоих полях разные подписи?

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Сравнение структур данных: Массивы и объекты в Javascript
Сравнение структур данных: Массивы и объекты в Javascript
Итак, вы изучили основы JavaScript и хотите перейти к изучению структур данных. Мотивация для изучения/понимания Структур данных может быть разной,...
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Создание собственной системы электронной коммерции на базе Keystone.js - настройка среды и базовые модели
Прошлая статья была первой из цикла статей о создании системы электронной коммерции с использованием Keystone.js, и она была посвящена главным образом...
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
0
0
37
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в вашем JavaScript заключается в том, что вы дважды объявляете переменные. Первый var canvas относится к первому элементу холста и через 12 строк после того, как та же переменная снова объявлена, теперь уже со вторым элементом холста. И то же самое касается всех остальных (глобальных) переменных.

Чтобы избежать этой проблемы, вам нужны либо разные переменные (например, var canvas1 = ... и var canvas2 = ...), либо вы избегаете использования глобальных переменных, потому что они не масштабируются и сбивают с толку. Альтернативой в этой ситуации является размещение переменных, которые вам нужны, в качестве свойств самого элемента холста. Примером может служить переменная drawing, которая является свойством каждого элемента холста.

Все функции обратного вызова (start, stop и draw) имеют параметр с именем e (объект события). На этом объекте вы можете найти target, который всегда относится к элементу холста, а на элементе холста вы можете найти drawing (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
  };
  // event listeners on the canvas element
  canvas.addEventListener("mousemove", draw);
  canvas.addEventListener("mouseup", stop);
  canvas.addEventListener("mousedown", 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;
}
canvas#signature {
  border: 2px solid black;
}

canvas#signature2 {
  border: 2px solid black;
}

form>* {
  margin: 10px;
}
<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>

это нормально, но почему я не получаю обе подписи после отправки формы?

Hamza Zafeer 10.04.2022 08:28

Нет, я просто исключил это в первую очередь. Теперь я добавил его снова. Я добавил имя в форму и добавил строку в функцию остановки, где URL-адрес данных добавляется как значение в скрытые поля.

chrwahl 10.04.2022 08:44

Другие вопросы по теме