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>

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>

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

  • 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">
    
  • 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


    There are a few things you need to do here.

  • On drop, get the (x,y) coords of the dragged target (the red dot):
  • function drop(ev) {
        ...
        var dataEl = document.getElementById(data);
        ev.target.appendChild(dataEl);
    
        // Get the dimensions (see https://developer.mozilla.org/en/docs/Web/API/Element/getBoundingClientRect)
        var rect = dataEl.getBoundingClientRect();
        var x = rect.x;
        var y = rect.y;
        ...
    }
    
  • The SVG needs some css:

  • position: fixed or position: absolute so that we can position it on top of the other elements.
  • z-index: 10 , where 10 is a number that is greater than the z-index of the other elements. This will make the line be displayed ontop instead of under the boxes/circles.
  • Continuing the drop function, we now want to set the position of the SVG's line to the positions of the circles. The tricky part here is that we need to know if its the first circle we are connecting a line to. To accomplish that, a boolean may be used in the form of something like isFirstConnectedEdge . If isFirstConnectedEdge === true , then you could ensure that you are setting the correct x,y values.

    For this example, lets use the heuristic of 'the first connected edge will always use the x1 and y1 values, the second connected edge and all further ones will set the x2 and y2. This would leave you in trouble if you wanted arrows to show direction of the edge, but we will leave that out for now. To crudely extend code from previous steps, we would be doing something like this in the drop function:

  • if (isFirstConnectedEdge) {
        s.style.x1 = x;
        s.style.y1 = y;
    } else {
        s.style.x2 = x;
        s.style.y2 = y;
        isFirstConnectedEdge = false;
    }
    
  • Finally, there are quite a few things you will need to consider. The line will be positioned to the top left of the circle's element. You will need to use something like var x = rect.x + (rect.width / 2) in order to get a centered line.
  • 链接地址: http://www.djcxy.com/p/37770.html

    上一篇: 你可以使用闭包优化进口函数吗?

    下一篇: 使用CSS和JavaScript在两个元素之间划一条线