【问题标题】:Correct algorithm to resize a rectangle on mouse drag在鼠标拖动时调整矩形大小的正确算法
【发布时间】:2020-08-03 10:45:53
【问题描述】:

我正在使用 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 的

但是一旦矩形被旋转,一切都会中断

谁能解释或链接我调整矩形大小并保持矩形的正确算法是什么?我认为这个问题已经得到解决,但我找不到任何有用的东西。

谢谢:)

【问题讨论】:

    标签: canvas geometry paperjs


    【解决方案1】:

    好的,我的蜜饯好朋友 zrugvanoudu35 快速解决了这个问题:

         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;
          }
    

    他是个聪明人。

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

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • 好的,这对我来说有点快。我会尝试以某种方式对此进行测试,但这并不容易,因为我必须计算大部分起始变量。我确实找到了一些可能对我有帮助的东西:paperjs.org/tutorials/geometry/vector-geometry 但请记住,我只能设置“点”值,而不能直接与矩形边宽/长度交互(据我所知)如果你有更多步骤通过逐步解释,我会接受的:)
      • 但是我不知道你的rotated矩形是如何定义的,所以给出了解决方案的大致轮廓。
      猜你喜欢
      • 2018-06-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多