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
Drawing a connecting line between two elements
提问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 的过程:
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)
<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.
in
<script>
tag writeline1 = $('#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 useoffset()
method too)
创建两个 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 文件总是好的)
<svg><line id="line1"/></svg>
Line 标签允许我们在两个指定的点 (x1,y1) 和 (x2,y2) 之间画一条线。(作为参考访问 w3schools。)我们还没有指定它们。因为我们将使用 jQuery 来编辑行标记的属性 (x1,y1,x2,y2)。
在
<script>
标签写入line1 = $('#line1'); div1 = $('#div1'); div2 = $('#div2');
我使用选择器来选择两个 div 和 line...
var pos1 = div1.position(); var pos2 = div2.position();
jQuery
position()
方法允许我们获取元素的当前位置。有关更多信息,请访问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.
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.
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
- 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
- https://beta.observablehq.com/@mbostock/collapsible-tree
- https://beta.observablehq.com/@mbostock/d3-force-directed-graph
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 的答案。