Изменение размера с привязкой во взаимодействии. js - PullRequest
0 голосов
/ 03 апреля 2020

В этом jsFiddle У меня есть интерактивный. js прямоугольник, размер которого можно изменить, сделав снимок 10 на 10 пикселей. Прямоугольник расположен в x = 95px, и когда я перемещаю левую сторону влево, он перемещается в x = 90x. Это хорошо, однако правая сторона также движется вправо, и не должна.

Что не так с этим кодом? Прямоугольник имеет ручки, это создает проблему?

  .on('resizemove', function(event) {

    const target = event.target.querySelector('rect');

    for (const attr of ['width', 'height']) {
      let v = Number(target.getAttribute(attr));
      v += event.deltaRect[attr];
      target.setAttribute(attr, Math.round(v/10)*10);
    }

    for (const attr of ['top', 'left']) {
      const a = attr == 'left' ? 'x' : 'y';
      let v = Number(target.getAttribute(a));
      v += event.deltaRect[attr];
      target.setAttribute(a, Math.round(v/10)*10);
    }

    findLocations(rect, handles);


 });

1 Ответ

1 голос
/ 03 апреля 2020

Ах, я вижу проблему. Вот что происходит: когда размер прямоугольника изменяется, вы округляете размер и положение. Это имеет следующий эффект:

  • У вас есть прямоугольник, стороны которого go от x = 95 до x = 115. Его левая сторона перемещена на -3 единиц. Теперь от 92 до 115.
  • Вы проверяете ширину: ее ширина составляет 115 - 92 = 23, поэтому вы округляетесь до ближайшей десяти: 20 единиц.
  • Вы проверьте положение: оно на 92, поэтому переместите его на 90. Это переместит весь прямоугольник с измененным размером.

Вам нужно будет обрабатывать дела top и left иначе, чем right и bottom случаи, так как первые два обновляют положение прямоугольников поверх их размера. Кроме того, вам нужно будет только округлить соответствующую сторону, которая была изменена: вы не хотите округлять дно при движении вправо.

  • Для left или top ...
    • Переместите x или y на новую позицию, округлите
    • Не округлите width или height, так как который будет двигаться right или bottom
  • Для right или bottom ...
    • Ничего не делать для x или y, поскольку их округление сместит весь прямоугольник на
    • Ну, мы все еще можем изменить x или y, так как они будут равны нулю, но мы не можем их округлить!
    • Только изменить width или hight, но в этот раз

Это довольно много случаев, чтобы проверить, но с помощью функции это не так уж сложно увидеть, как все это работает:

.on('resizemove', function(event) {
  const target = event.target.querySelector('rect');

  function changeVal(attr, change, round) {
    let val = Number(target.getAttribute(change));
    val += event.deltaRect[attr];
    if (round) val = Math.round(val / 10) * 10;
    target.setAttribute(change, val);
  }

  let round = false;
  if (event.deltaRect.top != 0) round = true;
  changeVal('top', 'y', round);

  round = false;
  if (event.deltaRect.left != 0) round = true;
  changeVal('left', 'x', round);

  round = false;
  if (event.deltaRect.right != 0) round = true;
  changeVal('width', 'width', round);

  round = false;
  if (event.deltaRect.bottom != 0) round = true;
  changeVal('height', 'height', round);

  findLocations(rect, handles);
});

Сокращение этого и переход к тому же стилю l oop, как и раньше:

.on('resizemove', function(event) {
  const target = event.target.querySelector('rect');

  const attributes = [
    { check: 'top', change: 'y' },
    { check: 'left', change: 'x' },
    { check: 'right', change: 'width' },
    { check: 'bottom', change: 'height' }
  ];

  for (const {check, change} of attributes) {
    let val = Number(target.getAttribute(change));
    val += event.deltaRect[check];
    if (event.deltaRect[check]) val = Math.round(val / 10) * 10;
    target.setAttribute(change, val);
  }

  findLocations(rect, handles);
});

Это использует ES6 деструктурирующее задание , поэтому оно не будет работать в IE.


Кажется, что при изменении размера левого края на правом крае все еще есть некоторая дрожь, но я думаю, что это ошибка с округлением ...?

Даже если нет, надеюсь, этого будет достаточно, чтобы вы начали.

...