How to calculate distance of x, y, width, height between three rectangle
Asked Answered
C

4

0

I'm working on a canvas that allows dragging shapes like Figma. I want to draw a guideline (x, y) when shapes intersect each other, just like below.

I already handled when shapes are snapped, so we don't need to calculate when they snap each other, basically, we know when should draw the lines. Just couldn't figure out the calculation of lines. Also, we already know the rect values when the shapes are snapped.

Edit:

Here is the codepen link that you can play with it. You'll see the shapes are not always drawing correctly.

https://codepen.io/lakers19/pen/ZEoPpKL

"firstRect":{ "x": 827, "y": 282, "width": 95, "height": 43, "right": 923,
            "bottom": 325,
            "top": 282,
            "left": 827,
        }
    
        "secondRect": { "x": 745, "y": 365, "width": 82, "height": 42, "right": 827,
            "bottom": 407,
            "top": 365,
            "left": 745,
        }
    
    {
        "currentRect": { "x": 938, "y": 369, "width": 134, "height": 80, "top": 369,
            "right": 1073,
            "bottom": 449,
            "left": 938
        }
    }

According to these values, I want to apply styles something like this:

  guideLineX.style.left = `.. px`
  guideLineX.style.top = `..px`
  guideLineX.style.width = '1px'
  guideLineX.style.height = `..px`

  guideLineY.style.left = `..px`
  guideLineY.style.top = `..px`
  guideLineY.style.width = `...px`
  guideLineY.style.height = '1px'

enter image description here

Crescantia answered 19/11, 2022 at 16:52 Comment(7)
It would be helpful if you post the, say, offending code too.Lemuroid
I have no idea in what relation these lines are two the rectangles. Looks arbitrary to meBalzer
if you look at closer than you will see the corners are related each other. @BalzerCrescantia
@Crescantia but you draw a line from the top of the top container. I would guess that the line should be from the bottom?Balzer
Hi @PauloSantos. I've created little PoC snipped that you can play with it. if you playing around the shapes you will see the lines not always correct. codepen.io/lakers19/pen/ZEoPpKLCrescantia
Do the lines need to connect to top corners only as in the pic? Wouldn't it look better if the vertical line in your picture joins to the bottom of the top rectangle? Why is the top right corner missing from the leftmost rectangle? Just trying to understand what you want. Are you hoping someone will write the code for you?Wahoo
@Mert, I've been playing with it in a lot of ways and I'm not seeing it be incorrect, could you include a pic of such a thing happening?Copepod
L
0

The thing is, you're trying to juggle too many things.

Even in your example, the lines are always between two objects, it so happens that one of the object interacts with two different ones.

Simply handle it differently: first handle the horizontal line, then handle the vertical line.

Lemuroid answered 22/11, 2022 at 20:43 Comment(0)
C
0

I will assume that the square that you move to get those red lines is rect and the others are firstRct and secondRect. This is just to make descriptions of what will happen al lot easier.

Try and disable the range check by changing line 192 to the following:

const inRange = true

If you now move around rect, you'll notice that it is not always the nearest edge of either firstRect or secondRect that corresponds with a red line. But you also notice that the red lines are always there, they do not vanish.

The second thing to notice is, that both red lines have different but fixed length, which is not what you want.

I'd calculate the nearest horizontal edge like this:

  var actualY;
  var distance = 1000000;
  const edges = [rect.top, rect.bottom ];
  for(e = 0; e < 2; e++){
    const edge = edges[e];
    candidates = [firstRect.top, firstRect.bottom, secondRect.top, secondRect.bottom ];
    for(c = 0; c < 4; c++){
      const candidate = candidates[c];
      const candidateDistance = Math.max(candidate,edge) - Math.min(candidate, edge);
      if(candidateDistance < distance){
        actualY = candidate;
        distance = candidateDistance;
      }
    }
  }

Obviously you can similarly calculate the nearest vertical edge.

You can now decide about displaying the red lines by looking at the distances. If the distance is below some small value such as 1, you'd display a red guiding line.

So for the horizontal line, we allready now the y-position, what about left and right? To calculate those, we first need to know, which shape it was, that caused the line to diplay. For c < 2 it is firstRect, otherwise it is secondRect. Let's call this the horizontalRect.

The left x-Position of the horizontal guiding line would then be the following:

  Math.min(rect.right, horizontalRect.right);

The right x-position:

  Math.max(rect.left, horizontalRect.left);
Cryogen answered 28/11, 2022 at 22:7 Comment(0)
B
0

Mathematically, that shouldn't take too much code. Except that you've invoked the idea of shapes. It looks like you're only doing rectangles which only have an x a y a w and a h. Please start another draft if it's rectangles, but please ignore me elsewise.

Burkes answered 29/11, 2022 at 4:13 Comment(0)
K
-1
if (tops of rectangles line up):
  draw a line on the top that connects the corners

if (left of rectangles line up):
  draw a line on the left that connects the corners

if (right of rectangles line up):
  draw a line on the right that connects the corners

if (bottom of rectangles line up):
  draw a line on the bottom that connects the corners
Kienan answered 23/11, 2022 at 23:36 Comment(1)
Doesn't the OP want a line if, for example, the left side of one rectangle lines up with the right side of another as in the picture?Wahoo

© 2022 - 2024 — McMap. All rights reserved.