2

I have drawn a line that connects between draggable divs. But, as the div is being dragged, the line looses its source and destination point (i.e from one div to other div). What my objective is to set the line in such a way that it should not losses its edge from any div and where ever i drag the div it keeps updating itself dynamically that is height, rotation, position.

Sorry for bad english. Please help.....! Here is my code

var coordinates = function(element) {
  element = $(element);
  var top = element.position().top;
  var left = element.position().left;

  //--------------line------------------------------
  var length = Math.sqrt(((left) * (left)) + ((top) * (top)));
  var angle = Math.atan2(top, left) * 180 / Math.PI;
  var transform = 'rotate(' + angle + 'deg)';

  $('#results').text('X: ' + left + ' ' + 'Y: ' + top).attr('style', 'margin-left:' + left + 'px');
  //$('#line1').attr('style', "margin-left:"+left+"px;margin-top:"+top+"px;height:"+(parseInt(100+top))+"px;transform:"+transform+";width:"+length+"px;");

  $('#line1').attr('style', "transform:" + transform + ";height:" + length + "px;");

}

//alert($('#box1').position().top);

$('#box1').draggable({
  start: function() {
    coordinates('#box1');
  },
  stop: function() {
    coordinates('#box1');
  }
});

$('#box2').draggable({
  start: function() {
    coordinates('#box2');
  },
  stop: function() {
    coordinates('#box2');
  }
});
.box {
  border: 1px solid black;
  background-color: #ccc;
  width: 100px;
  height: 100px;
  position: absolute;
}

.line {
  width: 1px;
  height: 100px;
  background-color: black;
  position: absolute;
}

#box1 {
  top: 0;
  left: 0;
}

#box2 {
  top: 200px;
  left: 0;
}

#box3 {
  top: 250px;
  left: 200px;
}

#line1 {
  top: 100px;
  left: 50px;
  /*transform: rotate(222deg);
    -webkit-transform: rotate(222deg);
    -ms-transform: rotate(222deg);*/
}

#line2 {
  top: 220px;
  left: 150px;
  height: 115px;
  transform: rotate(120deg);
  -webkit-transform: rotate(120deg);
  -ms-transform: rotate(120deg);
}
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>


<div class="line" id="line1"></div>


<div id="results">test</div>

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
user3162878
  • 598
  • 3
  • 10
  • 25

1 Answers1

7

If you make your line an svg element, then you can manipulate the x1, x2, y1 and y2 attributes of the line based on two boxes positions.

See example below:

const $b1 = $("#box1");
const $b2 = $("#box2");
const $line = $("line");
const padding = 7;
const coordinates = function() {
  const x1 = $b1.offset().left + $b1.width()/2-padding;
  const y1 = $b1.offset().top + $b1.height()/2-padding;
  const x2 = $b2.offset().left + $b1.width()/2-padding;
  const y2 = $b2.offset().top + $b1.height()/2-padding;

  $line.attr("x1", x1);
  $line.attr("y1", y1);
  $line.attr("x2", x2);
  $line.attr("y2", y2);
}
coordinates();


$('#box1').draggable({
  drag: coordinates
});

$('#box2').draggable({
  drag: coordinates
});
.box {
  border: 1px solid black;
  background-color: #ccc;
  width: 100px;
  height: 100px;
  position: absolute;
}


#box1 {
  top: 0;
  left: 0;
}

#box2 {
  top: 200px;
  left: 0;
}
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>

<svg height="1000" width="1000">
  <line id="line" x1="0" y1="0" x2="200" y2="200" style="stroke: rgb(0,0,0); stroke-width:1" />
</svg>


<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

If you want to use a div instead of an svg, the same result can be achieved using the createLine() method you provided:

const $b1 = $("#box1");
const $b2 = $("#box2");
const $line = $("#line");

const coordinates = function() {
  const x1 = $b1.offset().left + $b1.width()/2;
  const y1 = $b1.offset().top + $b1.height()/2;
  const x2 = $b2.offset().left + $b1.width()/2;
  const y2 = $b2.offset().top + $b1.height()/2;

  moveLine(x1, y1, x2, y2);  
}

coordinates();

function moveLine(x1, y1, x2, y2) {
    var length = Math.sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
    var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
    var transform = 'rotate(' + angle + 'deg)';

    offsetX = (x1 > x2) ? x2 : x1;
    offsetY = (y1 > y2) ? y2 : y1;
    
    $line.css({
        'position': 'absolute',
        '-webkit-transform': transform,
        '-moz-transform': transform,
        'transform': transform
      })
      .width(length)
      .offset({
        left: offsetX,
        top: offsetY
      });
}

$('#box1').draggable({
  drag: coordinates
});

$('#box2').draggable({
  drag: coordinates
});
.box {
  border: 1px solid black;
  background-color: #ccc;
  width: 100px;
  height: 100px;
  position: absolute;
}

#line1 {
  top: 100px;
  left: 50px;
  /*transform: rotate(222deg);
    -webkit-transform: rotate(222deg);
    -ms-transform: rotate(222deg);*/
}

.line {
  width: 1px;
  height: 1px;
  background-color: black;
  position: absolute;
  z-index: -1; /* put line behind the boxes */
}


#box1 {
  top: 0;
  left: 0;
}

#box2 {
  top: 200px;
  left: 0;
}
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>

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

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

For three boxes I suggest you add a data-connectattribute which specifies which boxes your line connects to. Then you can loop through each line and draw the lines connecting to each box:

const coordinates = function() {

  $(".line").each(function() {
    const [box1, box2] = $(this).data("connect").split(',');
    const $b1 = $(box1);
    const $b2 = $(box2);
    
    const x1 = $b1.offset().left + $b1.width()/2;
    const y1 = $b1.offset().top + $b1.height()/2;
  
    const x2 = $b2.offset().left + $b2.width()/2;
    const y2 = $b2.offset().top + $b2.height()/2;

    moveLine(x1, y1, x2, y2, $(this)); 
  });

   
}

coordinates();

function moveLine(x1, y1, x2, y2, $line) {
    var length = Math.sqrt(((x1 - x2) * (x1 - x2)) + ((y1 - y2) * (y1 - y2)));
    var angle = Math.atan2(y2 - y1, x2 - x1) * 180 / Math.PI;
    var transform = 'rotate(' + angle + 'deg)';

    var offsetX = (x1 > x2) ? x2 : x1;
    var offsetY = (y1 > y2) ? y2 : y1;
    
    $line.css({
        'position': 'absolute',
        '-webkit-transform': transform,
        '-moz-transform': transform,
        'transform': transform
      })
      .width(length)
      .offset({
        left: offsetX,
        top: offsetY
      });
}

$('.box').draggable({
  drag: coordinates
});
.box {
  border: 1px solid black;
  background-color: #ccc;
  width: 100px;
  height: 100px;
  position: absolute;
}

#line1 {
  top: 100px;
  left: 50px;
  /*transform: rotate(222deg);
    -webkit-transform: rotate(222deg);
    -ms-transform: rotate(222deg);*/
}

.line {
  width: 1px;
  height: 1px;
  background-color: black;
  position: absolute;
  z-index: -1; /* put line behind the boxes */
}


#box1 {
  top: 0;
  left: 0;
}

#box2 {
  top: 200px;
  left: 0;
}

#box3 {
  top: 200px;
  left: 200px;
}
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>
<div class="box" id="box3"></div>

<div class="line" id="line" data-connect="#box1,#box2"></div>
<div class="line" id="line2" data-connect="#box1,#box3"></div>
   

<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
Nick Parsons
  • 45,728
  • 6
  • 46
  • 64