Draw a connecting line between two elements

JavascriptHtmlConnectionLineJquery Ui-Draggable

Javascript Problem Overview


How can I draw a line between two or more elements to connect them? Any combination of HTML/CSS/JavaScript/SVG/Canvas is fine.

If your answer supports any of these, then do mention it:

  • draggable elements
  • draggable/editable connections
  • element overlap avoidance

> This question has been updated to consolidate the numerous variations of it.

Javascript Solutions


Solution 1 - Javascript

jsPlumb is an option available that supports drag and drop, as seen by its numerous demos, including the Flowchart demo.

It is available in a free Community edition and a paid Toolkit edition.

> The Toolkit edition wraps the Community edition with a comprehensive data binding layer, as well as several UI widgets for building applications and integrations for popular libraries, and is commercially licensed.

Solution 2 - Javascript

Joining lines with svgs was worth a shot for me, and it worked perfectly... first of all, Scalable Vector Graphics (SVG) is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation. SVG images and their behaviors are defined in XML text files. you can create an svg in HTML using <svg> tag. Adobe Illustrator is one of the best software used to create an complex svgs using paths.

Procedure to join two divs using a line :

  1. create two divs and give them any position as you need

     <div id="div1" style="width: 100px; height: 100px; top:0; left:0; background:#e53935 ; position:absolute;"></div>
     <div id="div2" style="width: 100px; height: 100px; top:0; left:300px; background:#4527a0 ; position:absolute;"></div>
    

(for the sake of explanation I am doing some inline styling but it is always good to make a separate css file for styling)

  1. <svg><line id="line1"/></svg>

Line tag allows us to draw a line between two specified points(x1,y1) and (x2,y2). (for a reference visit w3schools.) we haven't specified them yet. because we will be using jQuery to edit the attributes (x1,y1,x2,y2) of line tag.

  1. in <script> tag write

     line1 = $('#line1');   
     div1 = $('#div1');   
     div2 = $('#div2');
    

I used selectors to select the two divs and line...

    var pos1 = div1.position();
    var pos2 = div2.position();

jQuery position() method allows us to obtain the current position of an element. For more information, visit https://api.jquery.com/position/ (you can use offset() method too)

Now as we have obtained all the positions we need we can draw line as follows...

line1
  .attr('x1', pos1.left)
  .attr('y1', pos1.top)
  .attr('x2', pos2.left)
  .attr('y2', pos2.top);

jQuery .attr() method is used to change attributes of the selected element.

All we did in above line is we changed attributes of line from

x1 = 0
y1 = 0
x2 = 0
y2 = 0

to

x1 = pos1.left
y1 = pos1.top
x2 = pos2.left
y2 = pos2.top

as position() returns two values, one 'left' and other 'top', we can easily access them using .top and .left using the objects (here pos1 and pos2) ...

Now line tag has two distinct co-ordinates to draw line between two points.

Tip: add event listeners as you need to divs

Tip: make sure you import jQuery library first before writing anything in script tag

After adding co-ordinates through JQuery ... It will look something like this

Following snippet is for demonstration purpose only, please follow steps above to get correct solution

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="div1" style="width: 100px; height: 100px; top:0; left:0; background:#e53935 ; position:absolute;"></div>
<div id="div2" style="width: 100px; height: 100px; top:0; left:300px; background:#4527a0 ; position:absolute;"></div>

Solution 3 - Javascript

Recently, I have tried to develop a simple web app that uses drag and drop components and has lines connecting them. I came across these two simple and amazing javascript libraries:

  1. Plain Draggable: simple and high performance library to allow HTML/SVG element to be dragged.
  2. Leader Line: Draw a leader line in your web page

Working example link (usage: click on add scene to create a draggable, click on add choice to draw a leader line between two different draggables)

Solution 4 - Javascript

I also had the same requirement few days back

I used an full width and height svg and added it below all my divs and added lines to these svg dynamically.

Checkout the how I did it here using svg

HTML

<div id="ui-browser"><div class="anchor"></div>
     <div id="control-library" class="library">
       <div class="name-title">Control Library</div>
       <ul>
         <li>Control A</li>
         <li>Control B</li>
         <li>Control C</li>
         <li>Control D</li>
       </ul>
     </div><!--
--></div><!--
--><div id="canvas">
     <svg id='connector_canvas'></svg>
     <div class="ui-item item-1"><div class="con_anchor"></div></div>
     <div class="ui-item item-2"><div class="con_anchor"></div></div>
     <div class="ui-item item-3"><div class="con_anchor"></div></div>
     <div class="ui-item item-1"><div class="con_anchor"></div></div>
     <div class="ui-item item-2"><div class="con_anchor"></div></div>
     <div class="ui-item item-3"><div class="con_anchor"></div></div>
   </div><!--
--><div id="property-browser"></div>

https://jsfiddle.net/kgfamo4b/

    $('.anchor').on('click',function(){
   var width = parseInt($(this).parent().css('width'));
   if(width==10){
     $(this).parent().css('width','20%');
     $('#canvas').css('width','60%');
   }else{
      $(this).parent().css('width','10px');
     $('#canvas').css('width','calc( 80% - 10px)');
   }
});

$('.ui-item').draggable({
  drag: function( event, ui ) {
           var lines = $(this).data('lines');
           var con_item =$(this).data('connected-item');
           var con_lines = $(this).data('connected-lines');
  
           if(lines) {
             lines.forEach(function(line,id){
             		$(line).attr('x1',$(this).position().left).attr('y1',$(this).position().top+1);  
             }.bind(this));
           }
    
           if(con_lines){
               con_lines.forEach(function(con_line,id){
                  $(con_line).attr('x2',$(this).position().left)
                        .attr('y2',$(this).position().top+(parseInt($(this).css('height'))/2)+(id*5));
               }.bind(this));
              
           }
           
	   }
});

$('.ui-item').droppable({
  accept: '.con_anchor',
  drop: function(event,ui){
     var item = ui.draggable.closest('.ui-item');
     $(this).data('connected-item',item);
     ui.draggable.css({top:-2,left:-2});
     item.data('lines').push(item.data('line'));
    
     if($(this).data('connected-lines')){
        $(this).data('connected-lines').push(item.data('line'));
        
         var y2_ = parseInt(item.data('line').attr('y2'));
         item.data('line').attr('y2',y2_+$(this).data('connected-lines').length*5);
        
     }else $(this).data('connected-lines',[item.data('line')]);
    
     item.data('line',null);
    console.log('dropped');
  }
});


$('.con_anchor').draggable({drag: function( event, ui ) {
     var _end = $(event.target).parent().position();
     var end = $(event.target).position();
     if(_end&&end) 	
     $(event.target).parent().data('line')
       												.attr('x2',end.left+_end.left+5).attr('y2',end.top+_end.top+2);
},stop: function(event,ui) {
        if(!ui.helper.closest('.ui-item').data('line')) return;
        ui.helper.css({top:-2,left:-2});
        ui.helper.closest('.ui-item').data('line').remove();
        ui.helper.closest('.ui-item').data('line',null);
        console.log('stopped');
      }
});


$('.con_anchor').on('mousedown',function(e){
    var cur_ui_item = $(this).closest('.ui-item');
    var connector = $('#connector_canvas');
    var cur_con;
  
  if(!$(cur_ui_item).data('lines')) $(cur_ui_item).data('lines',[]);
  
  if(!$(cur_ui_item).data('line')){
         cur_con = $(document.createElementNS('http://www.w3.org/2000/svg','line'));
         cur_ui_item.data('line',cur_con);
    } else cur_con = cur_ui_item.data('line');
  
    connector.append(cur_con);
    var start = cur_ui_item.position();
     cur_con.attr('x1',start.left).attr('y1',start.top+1);
     cur_con.attr('x2',start.left+1).attr('y2',start.top+1);
});

Solution 5 - Javascript

VisJS supports this with its Arrows example, that supports draggable elements.

It also supports editable connections, with its Interaction Events example.

Solution 6 - Javascript

GoJS supports this, with its State Chart example, that supports dragging and dropping of elements, and editing of connections.

> This answer is based off of Walter Northwoods' answer.

Solution 7 - Javascript

Raphaël supports this, with its Graffle example.

> This answer is based off of Awais Akhtar's answer, and Vaibhav Jain's answer.

Solution 8 - Javascript

Solution 9 - Javascript

mxGraph — used by draw.io — supports this use case, with its Grapheditor example. Documentation. Examples.

> This answer is based off of Vainbhav Jain's answer.

Solution 10 - Javascript

Cytoscape supports this with its Architecture example which supports dragging elements.

For creating connections, there is the edgehandles extension. It does not yet support editing existing connections. Question.

For editing connection shapes, there is the edge-editing extension. Demo.

The edit-editation extension seems promising, however there is no demo yet.

Solution 11 - Javascript

js-graph.it supports this use case, as seen by its getting started guide, supporting dragging elements without connection overlaps. Doesn't seem like it supports editing/creating connections. Doesn't seem it is maintained anymore.

Solution 12 - Javascript

JointJS/Rappid supports this use case with its Kitchensink example which supports dragging and dropping of elements, and repositioning of connections. It has many examples.

> This answer is based off of Vainbhav Jain's answer.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBakhtiyorView Question on Stackoverflow
Solution 1 - JavascriptTomasz KowalczykView Answer on Stackoverflow
Solution 2 - JavascriptAniView Answer on Stackoverflow
Solution 3 - JavascriptCherubimView Answer on Stackoverflow
Solution 4 - JavascriptNadir LaskarView Answer on Stackoverflow
Solution 5 - JavascriptbaluptonView Answer on Stackoverflow
Solution 6 - JavascriptbaluptonView Answer on Stackoverflow
Solution 7 - JavascriptbaluptonView Answer on Stackoverflow
Solution 8 - JavascriptbaluptonView Answer on Stackoverflow
Solution 9 - JavascriptbaluptonView Answer on Stackoverflow
Solution 10 - JavascriptbaluptonView Answer on Stackoverflow
Solution 11 - JavascriptbaluptonView Answer on Stackoverflow
Solution 12 - JavascriptbaluptonView Answer on Stackoverflow