1

I am trying to draw a path between points wihtout using canvas or any other librares. Everything works fine for positive degrees, but it doesn't for negative..

My "points" are 150x150 [px], that's why there is that +75px in left position.

This is my code:

  useEffect(() => {
    let x1 = spider1.x;
    let y1 = spider1.y;
    let x2 = spider2.x;
    let y2 = spider2.y;

    if (x1 > x2) {
      let xTmp = x1;
      let yTmp = y1;
      x1 = x2;
      y1 = y2;
      x2 = xTmp;
      y2 = yTmp;
    }
    if (x1 === x2) {
      const height = Math.abs(y2 - y1).toString();
      setStyle({
        width: '5px',
        left: (x1 + 75).toString() + 'px',
        top: `${Math.min(y1, y2) + 75}px`,
        height: `${height}px`,
        transform: 'rotate(0deg)'
      });
    } else {
      const a = (y2 - y1) / (x2 - x1);
      const radians = Math.atan(a);
      const degrees = radians * (180 / Math.PI);

      setStyle({
        width: `${Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1))}px`,
        left: (x1 + 75).toString() + 'px',
        top: `${Math.min(y1, y2) + 75}px`,
        height: `5px`,
        transform: `rotate(${degrees}deg)`,
        transformOrigin: `${degrees > 0 ? '0% 0%' : '100% 100%'}`
      });
    }
  }, [spider1, spider2]);

  return <div className='net' style={style} ref={myRef}></div>;

And the net class:

.net {
  position: absolute;
  background-color: red;
  z-index: 90;
}

On the screens we have the same objects, but the degrees on the second one are "-" and the line doesn't connect that two squares because of that

photo1 photo2

poldeeek
  • 313
  • 2
  • 16
  • 1
    Not sure all of your problems but the first glaring one is your x1 y1 x2 y2 variables all reference the opposite axis. I.e `x1 = spider1.y` – Justin Jun 21 '21 at 22:52
  • Oh.. I didn't notice that earlier, but this is my bad during create a spider object. Anyway that little mistake doesn't cause the problem. I updated the post with two screens where you can see the problem better – poldeeek Jun 21 '21 at 23:01
  • The problem is atan and it needs to be atan2. Check out https://stackoverflow.com/questions/283406/what-is-the-difference-between-atan-and-atan2-in-c – John Jun 22 '21 at 00:45
  • I did it like that: `const degrees = (Math.atan2(y2 - y1, x2 - x1) * 180) / Math.PI;`, but the result is the same – poldeeek Jun 22 '21 at 02:04
  • const radians = Math.atan2(y2 - y1, x2 - x1); is probably what you want. Without a working code I can't give an exact answer. – John Jun 22 '21 at 02:06
  • Yes, it tried that and didn't work. Sorry for my often editing. Just keep working on that and discover new things. Here is code of that component - https://github.com/poldeeek/spider-game/blob/main/frontend/src/components/Net/Net.tsx there is that component – poldeeek Jun 22 '21 at 02:10
  • Yeah, we wrote our message at the same time - Anyway my example with atan2 is below – John Jun 22 '21 at 02:51

1 Answers1

1

This example works. You will have to compare yours with mine as to what the differences are.

Note: I just wrote it from scratch rather using your example.

Just click "Random position"

var button = document.getElementById("new-points");

button.onclick = function() {

  var xy1 = {
       m_x : Math.floor((Math.random() * 200) + 1),
     m_y : Math.floor((Math.random() * 200) + 1),
   };
  
   var xy2 = {
      m_x : Math.floor((Math.random() * 200) + 1),
      m_y : Math.floor((Math.random() * 200) + 1),
   };
  
   var dotA =  document.getElementById("dotA");
   dotA.style.left = (xy1.m_x - 5) + "px";
   dotA.style.top = (xy1.m_y - 5) + "px";

   var dotB =  document.getElementById("dotB");
   dotB.style.left = (xy2.m_x - 5) + "px";
   dotB.style.top = (xy2.m_y - 5) + "px";

   var line = document.getElementById("line");
            
   var distance = Math.hypot(xy2.m_x - xy1.m_x, xy2.m_y - xy1.m_y);
            
   line.style.width = distance + "px";
   line.style.left = xy1.m_x + "px";
   line.style.top = xy1.m_y + "px";
            
   var angle = ((Math.atan2(xy1.m_x - xy2.m_x, xy2.m_y - xy1.m_y) + (Math.PI / 2.0)) * 180 / Math.PI);
   line.style.transform = "rotate(" + angle + "deg)";
   line.style.display = "block";
}
#new-points {
  border: 1px solid black;
  padding: 5px;
  width: 200px;
  text-align: center;
}

.dot {
   position: absolute;
   width: 10px;
   height: 10px;
   background: blue;
 }
 
 #line {
   position: absolute;
   border-top: solid 1px red;
   height: 1px;
   max-height: 1px;
   transform-origin: 0% 0%;
 }
<div id="dotA" class="dot"></div>

<div id="dotB" class="dot"></div>
<div id="line"></div>


<div id="new-points" style="">
Random position
</div>

I've also tried the atan method for the above and it doesn't work. You can try it yourself and see what happens.

John
  • 3,716
  • 2
  • 19
  • 21
  • The problem was `top: '${Math.min(y1, y2) + 75}px'` - should be `top: '${y1 + 75}px'` and the transform origin should be always 0% 0%. Thank you ! :D – poldeeek Jun 22 '21 at 09:36
  • I've also tried used the `atan()` method and in my case it worked. Anyway I will stay with `atan2()` – poldeeek Jun 22 '21 at 09:47