开发者

Draw a connecting line between two elements [closed]

Closed. This question is seeking recommendations for boo开发者_高级运维ks, tools, software libraries, and more. It does not meet Stack Overflow guidelines guidelines. It is not currently accepting answers.

We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.

Closed 2 years ago.

The community reviewed whether to reopen this question 11 months ago and left it closed:

Original close reason(s) were not resolved

Improve this question

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.


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.


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>


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)


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


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

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


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.


Raphaël supports this, with its Graffle example.

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


D3 has hundreds of examples, some of which are suitable for this question.

Examples without drag and drop, that are fixed:

  • https://beta.observablehq.com/@mbostock/d3-cluster-dendrogram
  • https://beta.observablehq.com/@mbostock/d3-tidy-tree
  • https://beta.observablehq.com/@mbostock/d3-hierarchical-edge-bundling
  • https://beta.observablehq.com/@mbostock/d3-radial-dendrogram
  • https://beta.observablehq.com/@mbostock/d3-sankey-diagram
  • https://www.jasondavies.com/collatz-graph/
  • https://bost.ocks.org/mike/hive/
  • https://bost.ocks.org/mike/fisheye/
  • https://bl.ocks.org/wvengen/cab9b01816490edb7083

Examples without drag and drop, that are interactive:

  • https://beta.observablehq.com/@mbostock/collapsible-tree
  • https://beta.observablehq.com/@mbostock/d3-force-directed-graph

Examples with dragging and dropping:

  • http://bl.ocks.org/MoritzStefaner/1377729
  • http://bl.ocks.org/Neilos/584b9a5d44d5fe00f779

This answer is based off of Glenn Dayton's 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.


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜