Javascript 绘制两个元素之间的连接线

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6278152/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 21:04:04  来源:igfitidea点击:

Drawing a connecting line between two elements

javascripthtmlconnectionlinejquery-ui-draggable

提问by Bakhtiyor

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.

我如何(或可用的工具)在两个或多个元素之间绘制一条线以连接它们?HTML/CSS/JavaScript/SVG/Canvas 的任何组合都可以。

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 variationsof it.

这个问题已经更新,以整合的众多变体

回答by Tomasz Kowalczyk

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

jsPlumb是一个支持拖放的可用选项,如其众多演示所见,包括流程图演示

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

它有免费的社区版和付费的 Toolkit 版。

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.

Toolkit 版本用一个全面的数据绑定层以及几个 UI 小部件来包装社区版本,用于为流行的库构建应用程序和集成,并且已获得商业许可。

回答by Ani

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.

将线条与 svgs 连接起来对我来说值得一试,而且效果很好……首先,可伸缩矢量图形 (SVG) 是一种基于 XML 的矢量图像格式,用于二维图形,支持交互性和动画。SVG 图像及其行为在 XML 文本文件中定义。您可以使用<svg>标签在 HTML 中创建 svg 。Adobe Illustrator 是用于使用路径创建复杂 svg 的最佳软件之一。

Procedure to join two divs using a line :

使用一行连接两个 div 的过程:

  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)

  1. 创建两个 div 并根据需要为它们提供任何位置

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

    (为了解释起见,我正在做一些内联样式,但为样式制作单独的 css 文件总是好的)

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

    Line 标签允许我们在两个指定的点 (x1,y1) 和 (x2,y2) 之间画一条线。(作为参考访问 w3schools。)我们还没有指定它们。因为我们将使用 jQuery 来编辑行标记的属性 (x1,y1,x2,y2)。

  3. <script>标签写入

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

    我使用选择器来选择两个 div 和 line...

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

    jQueryposition()方法允许我们获取元素的当前位置。有关更多信息,请访问https://api.jquery.com/position/(您也可以使用offset()方法)

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.

jQuery.attr()方法用于更改所选元素的属性。

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

我们在上面所做的只是改变了 line 的属性

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

由于position()返回两个值,一个是“left”,另一个是“top”,我们可以使用对象(此处为 pos1 和 pos2)使用 .top 和 .left 轻松访问它们...

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

现在线标签有两个不同的坐标来在两点之间画线。

Tip: add event listeners as you need to divs

提示:根据需要添加事件侦听器到 div

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

提示:在 script 标签中写入任何内容之前,请确保先导入 jQuery 库

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

通过 JQuery 添加坐标......它看起来像这样

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>

回答by Nadir Laskar

I also had the same requirement few days back

几天前我也有同样的要求

I used an full widthand heightsvgand added it below all my divs and added linesto these svg dynamically.

我使用了全和全svg并将其添加到我所有的 div 下方,并动态地向这些 svg添加了线条

Checkout the how I did it here using svg

使用svg查看我是如何做到的

HTML

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/

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

回答by balupton

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

VisJS通过其Arrows 示例支持这一点,该示例支持可拖动元素。

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

它还支持可编辑的连接,以及它的交互事件示例

回答by balupton

js-graph.itsupports 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.

js-graph.it支持这个用例,从它的入门指南可以看出,支持没有连接重叠的拖动元素。它似乎不支持编辑/创建连接。好像不再维护了。

回答by balupton

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

mxGraph— 由draw.io使用 — 支持此用例,其Grapheditor 示例文档。例子。

This answer is based off of Vainbhav Jain'sanswer.

这个答案基于Vainbhav Jain 的答案

回答by balupton

Cytoscapesupports this with its Architecture examplewhich supports dragging elements.

Cytoscape以其支持拖动元素的架构示例支持这一点。

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

为了创建连接,有edgehandles扩展。它尚不支持编辑现有连接。题。

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

对于编辑连接形状,有边缘编辑扩展。演示。

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

编辑editation扩展很有前途,但没有演示呢。

回答by balupton

Rapha?lsupports this, with its Graffle example.

Rapha?l支持这一点,它的Graffle 示例

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

这个答案基于Awais Akhtar 的答案Vaibhav Jain 的答案

回答by balupton

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

D3数百个例子,其中一些适合这个问题。

Examples without drag and drop, that are fixed:

没有拖放的例子,是固定的:

Examples without drag and drop, that are interactive:

没有拖放的示例是交互式的:

Examples with dragging and dropping:

拖放示例:

This answer is based off of Glenn Dayton'sanswer.

这个答案基于格伦代顿的答案

回答by balupton

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

GoJS通过其State Chart 示例支持这一点,该示例支持元素的拖放和连接的编辑。

This answer is based off of Walter Northwoods'answer.

这个答案基于Walter Northwoods 的答案