Make a line between two elements using CSS and JavaScript

I am trying to draw a line between two points on my page. Images are dragged and placed in the DIV, so their position may change, but the line should still connect them.

So far I have tried this with just a custom string.

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> 
+7
javascript html css
source share
3 answers

Well, as mentioned in the comments, relatively easy when the dots are on the same line.

Everything becomes more complicated if you have one on top of the other - then you basically need: an angle to apply it to the CSS transform: rotate the property and the length between two points / elements to recalculate the width, since it is not a straight line, I I hate math :), so I used the knowledge of good people from the Internet: http://jsfiddle.net/codepo8/bAwUf/light/ ( codepo8 loans)

The two most important lines are:

 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 look 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 a good starting point, I think (there are few things left to make it perfect), but I think you will get it ...

DEMO (it’s better to see it here, the fragments are not large, for such demonstrations): https://jsfiddle.net/dxre19o6/

+2
source share

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

  • Adjust the SVG to become your background. Thus, it will not interfere with clicking 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"> 
  • In the transition, you need to move the line, capturing the position of the points and changing the coordinates x1,y1,x2,y2 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

+1
source share

There are a few things you need to do here.

  • In the case of a drop, get the coordinates (x, y) of the target being dragged (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; ... } 
  1. SVG needs some kind of css:

    • position: fixed or position: absolute so that we can position it on top of other elements.
    • z-index: 10 , where 10 is a number greater than the z-index of other elements. This will cause the row to be displayed on the table instead of fields / circles.
  2. Continuing the drop function, we now want to set the position of the SVG line to the position of the circles. The hard part here is that we need to know if its first circle is connected to the line. For this, a boolean value can be used in the form of something like isFirstConnectedEdge . If isFirstConnectedEdge === true , you can make sure that you specify the correct x, y values.

    In this example, you can use the heuristic "the first bound edge will always use the values ​​x1 and y1, the second bound edge and all the others will set x2 and y2. This will leave you in trouble if you want the arrows to show the direction of the edge, but this time we will leave this in. To roughly extend the code from the previous steps, we will do something similar 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; } 
  1. Finally, there are many things that you will need to consider. The line will be located in the upper left corner of the circle element. You will need to use something like var x = rect.x + (rect.width / 2) to get a centered line.
0
source share

All Articles