Ах, я вижу проблему. Вот что происходит: когда размер прямоугольника изменяется, вы округляете размер и положение. Это имеет следующий эффект:
- У вас есть прямоугольник, стороны которого 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.
Кажется, что при изменении размера левого края на правом крае все еще есть некоторая дрожь, но я думаю, что это ошибка с округлением ...?
Даже если нет, надеюсь, этого будет достаточно, чтобы вы начали.