Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a Line between two elements using CSS and JavaScript

I am attempting to have a line go between the two dots on my page. The images are draggable and placeable into the DIVs so their position can change yet the line still needs to connect them.

So far I have tried this with only a custom line to start there.

var s = document.getElementById("Red1X");
var x = 200, y = 200;
s.style.x2 = x + "px";
s.style.y2 = y + "px";

function allowDrop(ev) {
    ev.preventDefault();
}
function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
}
#div1 {
    width: 17px;
    height: 17px;
    padding: 0px;
    border: 1px solid #aaaaff;
    float: left
}
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

<img id="RED1" src="http://i.imgur.com/By4xvE5.png" draggable="true" ondragstart="drag(event)" align="left">

<img id="RED2" src="http://i.imgur.com/By4xvE5.png" draggable="true" ondragstart="drag(event)" align="left">

<svg height="500" width="500">
  <line id="Red1X" x1="0" y1="0" x2="100" y2="200" style="stroke:rgb(255,0,0);stroke-width:3" />
</svg>
like image 967
Mark Avatar asked Jan 06 '17 18:01

Mark


People also ask

How do you put a line between divs?

There are two ways to add a horizontal line between two divs. First, put a <hr> tag between the two divs, and the second is to place any block-level element such as a div, p, etc, between the two divs and apply a bottom or top border on it. Either way, you can achieve the same task.

How do I put two elements on the same line in CSS?

To get all elements to appear on one line the easiest way is to: Set white-space property to nowrap on a parent element; Have display: inline-block set on all child elements.


2 Answers

Ok, as mentioned in comments, it is relatively easy when dots are in same line.

Things get more complicated if you have one above another - then you basically need: angle, to apply it to CSS transform:rotate property, and length between two dots/elements, to recalculate width, since it is not straight line anymore. I hate math :), so i used knowledge from good people from internet: http://jsfiddle.net/codepo8/bAwUf/light/ (credits to codepo8)

Two most important lines:

var angle= Math.atan2(red2.offsetTop - red1.offsetTop, red2.offsetLeft - red1.offsetLeft) * 180 / Math.PI;
var length = Math.sqrt((red2.offsetLeft-red1.offsetLeft) * (red2.offsetLeft-red1.offsetLeft) + (red2.offsetTop-red1.offsetTop) * (red2.offsetTop-red1.offsetTop));

And now, your script should be like this:

var s = document.querySelector(".line");
red1=document.getElementById('RED1');
red2=document.getElementById('RED2');

function allowDrop(ev) {
    ev.preventDefault();
}
function drag(ev) {
    ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
    ev.preventDefault();
    var data = ev.dataTransfer.getData("text");
    ev.target.appendChild(document.getElementById(data));
 
    s.style.left=red1.offsetLeft+5+'px';
    s.style.top=red1.offsetTop+5+'px';
    
     s.style.visibility='visible';
var angle= Math.atan2(red2.offsetTop - red1.offsetTop, red2.offsetLeft - red1.offsetLeft) * 180 / Math.PI;
var length = Math.sqrt((red2.offsetLeft-red1.offsetLeft) * (red2.offsetLeft-red1.offsetLeft) + (red2.offsetTop-red1.offsetTop) * (red2.offsetTop-red1.offsetTop));
 s.style.width=Math.abs(length)+'px';

     
       s.style.transform="rotate("+Math.round(angle)+"deg)";
       s.style.transformOrigin ="0 0"; 
     
  
    
}
.div1 {
    width: 150px;
    height: 150px;
    padding: 0px;
    border: 1px solid #aaaaff;
    float: left;
   
}
.line {
  position:absolute;
  height:3px;
  background:red;
  width:100px;
  z-index:999;
  visibility:hidden;
}
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

<img id="RED1" src="http://i.imgur.com/By4xvE5.png" draggable="true" ondragstart="drag(event)" align="left">

<img id="RED2" src="http://i.imgur.com/By4xvE5.png" draggable="true" ondragstart="drag(event)" align="left">



<div class="line">

</div>

This is good starting point, i guess (few things are left to make it perfect), but i think i you will get it...

DEMO (better to see it here, snippets are not great, for this kind of demos): https://jsfiddle.net/dxre19o6/

like image 139
sinisake Avatar answered Oct 15 '22 11:10

sinisake


Here is one example that uses jQuery and the jQuery UI positioning plugin.

  1. Adjust the SVG so that it becomes your background. That way, it won't get in the way of trying to click on the dots.

    <svg style="position:absolute;top:0;left:0;height:100%;bottom:100%;z-index:-1">
      <line id="Red1X" x1="0" y1="0" x2="100" y2="200" style="stroke:rgb(255,0,0);stroke-width:3" />
    </svg>
    <div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <div class="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <img id="RED1" src="http://i.imgur.com/By4xvE5.png" draggable="true" ondragstart="drag(event)" align="left">
    <img id="RED2" src="http://i.imgur.com/By4xvE5.png" draggable="true" ondragstart="drag(event)" align="left">
    
  2. On drop, you need to reposition the line by grabbing the position of the dots and modifying the x1,y1,x2,y2 coordinates of the SVG.

    function positionLine(){
        d1.data('position', d1.position());
        d2.data('position', d2.position());
        line.attr('x1', d1.data('position').left + (d1.width() / 2));
        line.attr('y1', d1.data('position').top + (d1.height() / 2));
        line.attr('x2', d2.data('position').left + (d2.width() / 2));
        line.attr('y2', d2.data('position').top + (d2.height() / 2));
    }
    

Here is a working Plunker: https://plnkr.co/edit/1fVBcqRsxc7r6gFZx0bR?p=preview

like image 41
Michael Sacket Avatar answered Oct 15 '22 10:10

Michael Sacket