在鼠标拖动时调整矩形大小的正确算法
Correct algorithm to resize a rectangle on mouse drag
我正在使用 paper.js 制作关卡编辑器。我目前正在纠结如何正确调整矩形大小
目前,我正在做类似的事情:
rect.onMouseDrag = event => {
let selectedNode = rect.selectedNode;
selectedNode.point.x += event.delta.x;
selectedNode.point.y += event.delta.y;
switch (rect.selectedNode.index) {
case 0:
rect.segments[1].point.x += event.delta.x;
rect.segments[3].point.y += event.delta.y;
break;
case 1:
rect.segments[0].point.x += event.delta.x;
rect.segments[2].point.y += event.delta.y;
break;
case 2:
rect.segments[3].point.x += event.delta.x;
rect.segments[1].point.y += event.delta.y;
break;
case 3:
rect.segments[selectedNode.index - 1].point.x += event.delta.x;
rect.segments[selectedNode.index - 3].point.y += event.delta.y;
break;
};
所以我只是检查相邻的点并相应地移动它们到鼠标事件。
它适用于 AABB
但是一旦矩形旋转,一切都崩溃了
任何人都可以解释或只是 link 我调整矩形大小并保持矩形的正确算法是什么?我认为这个问题已经得到解决,但我找不到任何有用的东西。
谢谢:)
将鼠标移动矢量投影到矩形边矢量上(它们取决于旋转角度)并对矩形边长应用相应的更改。
矩形的一个边具有单位方向矢量 (cos(fi), sin(fi))
,另一个(相邻)边 - (-sin(fi), cos(fi))
并且鼠标移动 (mx, my)
应用于这些边之间的顶点:
delta_width = mx * cos(fi) + my * sin(fi)
delta_height = -mx * sin(fi) + my * cos(fi)
注意符号取决于移动的顶点
好的,我的蜜饯zrugvanoudu35 speedrund 的好朋友解决了这个问题:
switch (rect.selectedNode.index) {
case 0:
rect.segments[1].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[1].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[3].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[3].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
case 1:
rect.segments[0].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[0].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[2].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[2].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
case 2:
rect.segments[3].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[3].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[1].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[1].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
case 3:
rect.segments[2].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[2].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[0].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[0].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
}
他是个有智慧的人。
显然这需要一些重构,但这样更容易 post 综合答案。
我正在使用 paper.js 制作关卡编辑器。我目前正在纠结如何正确调整矩形大小
目前,我正在做类似的事情:
rect.onMouseDrag = event => {
let selectedNode = rect.selectedNode;
selectedNode.point.x += event.delta.x;
selectedNode.point.y += event.delta.y;
switch (rect.selectedNode.index) {
case 0:
rect.segments[1].point.x += event.delta.x;
rect.segments[3].point.y += event.delta.y;
break;
case 1:
rect.segments[0].point.x += event.delta.x;
rect.segments[2].point.y += event.delta.y;
break;
case 2:
rect.segments[3].point.x += event.delta.x;
rect.segments[1].point.y += event.delta.y;
break;
case 3:
rect.segments[selectedNode.index - 1].point.x += event.delta.x;
rect.segments[selectedNode.index - 3].point.y += event.delta.y;
break;
};
所以我只是检查相邻的点并相应地移动它们到鼠标事件。 它适用于 AABB
但是一旦矩形旋转,一切都崩溃了
任何人都可以解释或只是 link 我调整矩形大小并保持矩形的正确算法是什么?我认为这个问题已经得到解决,但我找不到任何有用的东西。
谢谢:)
将鼠标移动矢量投影到矩形边矢量上(它们取决于旋转角度)并对矩形边长应用相应的更改。
矩形的一个边具有单位方向矢量 (cos(fi), sin(fi))
,另一个(相邻)边 - (-sin(fi), cos(fi))
并且鼠标移动 (mx, my)
应用于这些边之间的顶点:
delta_width = mx * cos(fi) + my * sin(fi)
delta_height = -mx * sin(fi) + my * cos(fi)
注意符号取决于移动的顶点
好的,我的蜜饯zrugvanoudu35 speedrund 的好朋友解决了这个问题:
switch (rect.selectedNode.index) {
case 0:
rect.segments[1].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[1].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[3].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[3].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
case 1:
rect.segments[0].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[0].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[2].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[2].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
case 2:
rect.segments[3].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[3].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[1].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[1].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
case 3:
rect.segments[2].point.x +=
event.delta.x * Math.cos(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.sin(rad);
rect.segments[2].point.y +=
event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.sin(rad) * Math.sin(rad);
rect.segments[0].point.x +=
event.delta.x * Math.sin(rad) * Math.sin(rad) +
-event.delta.y * Math.sin(rad) * Math.cos(rad);
rect.segments[0].point.y +=
-event.delta.x * Math.sin(rad) * Math.cos(rad) +
event.delta.y * Math.cos(rad) * Math.cos(rad);
break;
}
他是个有智慧的人。
显然这需要一些重构,但这样更容易 post 综合答案。