Canvas 鼠标拖动时调整矩形大小的正确算法

Canvas 鼠标拖动时调整矩形大小的正确算法,canvas,geometry,paperjs,Canvas,Geometry,Paperjs,我正在使用paper.js制作一个关卡编辑器。我目前正在研究如何正确调整矩形的大小 目前,我正在做如下工作: rect.onMouseDrag = event => { let selectedNode = rect.selectedNode; selectedNode.point.x += event.delta.x; selectedNode.point.y += event.delta.y; switch (rect.selectedNo

我正在使用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的工作很好

但一旦矩形旋转,所有东西都会断裂

有人能解释一下或者直接联系我调整矩形大小并保持矩形的正确算法是什么吗?我想这个问题已经解决了,但我找不到任何有用的东西


谢谢:)

将鼠标移动向量投影到矩形边向量上(它们取决于旋转角度),并对矩形边长度应用相应的更改

一个矩形侧具有单位方向向量
(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)

请注意,符号取决于移动的顶点

将鼠标移动向量投影到矩形边向量上(它们取决于旋转角度),并对矩形边长度应用相应的更改

一个矩形侧具有单位方向向量
(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 SpeedRun解决了这个问题:

     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;
      }
他是个聪明人


显然,这需要一些重构,但以这种方式发布综合答案更容易。

好的,我的好朋友zrugvanoudu35 Speedrun解决了这个问题:

     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;
      }
他是个聪明人


显然,这需要一些重构,但这样发布综合答案更容易。

好的,这对我来说有点快。我将尝试以某种方式测试这一点,但这并不容易,因为我必须计算大多数初始变量。我确实发现了一些可能对我有帮助的东西:但请记住,我只能设置“点”值,不能直接与矩形边宽度/长度交互(据我所知),如果您有更详细的逐步解释,我将接受:)但我不知道旋转矩形是如何定义的,所以给出了解决方案的概要。好的,这对我来说有点快。我将尝试以某种方式测试这一点,但这并不容易,因为我必须计算大多数初始变量。我确实发现了一些可能对我有帮助的东西:但请记住,我只能设置“点”值,不能直接与矩形边宽度/长度交互(据我所知),如果您有更详细的逐步解释,我将接受:)但我不知道旋转矩形是如何定义的,因此给出了解决方案的大致轮廓。