Drawing a connecting line between two elements

How can I (or what tools are available) for drawing 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.

Answers:

Answer

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.

Answer

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)

  2. <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.

  3. 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>
<svg width="500" height="500"><line x1="50" y1="50" x2="350" y2="50" stroke="red"/></svg>

Answer

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);
});
Answer

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

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

Answer

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.

Answer

Raphaël supports this, with its Graffle example.

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

Answer

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.

Answer

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.

Answer

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.

Answer

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.

Answer

Recently I was trying build drag and drop components and 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
Answer

For those looking for this in 2020, check out Angular cool Line ! It allows you draw fancy curvy arrows between two DOM elements. Example

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.