在这个jsFiddle中,我有一个interact.js rect,它可以通过10px乘以10px的快照来调整大小。rect位于x=95px,当我将左侧向左移动时,它将移动到x=90x。这很好,但右侧也会向右移动,不应该。
这个代码出了什么问题?rect有句柄,这是造成问题的原因吗?
.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);
});
啊,我看到问题了。发生的情况是:当调整矩形的大小时,您将对大小和位置进行四舍五入。这具有以下效果:
- 有一个矩形,它的边从
x = 95
到x = 115
。它的左侧移动了-3
单元。现在是92
到115
- 检查宽度:宽度为
115 - 92 = 23
个单位,因此四舍五入到最接近的十位:20
个单位 - 你检查一下位置:它在
92
上,所以你把它移到90
上这将滑动整个已调整大小的矩形
您需要处理与right
和bottom
不同的top
和left
情况,因为前两种情况会更新其大小顶部的矩形位置。最重要的是,你只需要绕过被改变的一侧:当你向右移动时,你不想绕过底部。
- 对于
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);
});
缩短并更改为与以前相同的循环样式:
.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中不起作用。
调整左边缘的大小时,右边缘似乎仍然有一些刺耳的声音,但我认为这是舍入的错误。。。?
即使没有,我希望这足以让你开始。