두 요소 사이의 연결선 그리기 [닫힘]


106

두 개 이상의 요소 사이에 선을 그려 연결하려면 어떻게해야합니까? HTML / CSS / JavaScript / SVG / Canvas의 모든 조합이 좋습니다.

귀하의 답변이 다음 중 하나를 지원하는 경우 언급하십시오.

  • 드래그 가능한 요소
  • 드래그 가능 / 편집 가능한 연결
  • 요소 중복 방지

이 질문은 다양한 변형통합하기 위해 업데이트되었습니다 .

답변:


164

jsPlumbFlowchart 데모를 포함한 수많은 데모 에서 볼 수 있듯이 드래그 앤 드롭을 지원하는 옵션 입니다.

무료 커뮤니티 에디션과 유료 툴킷 에디션으로 제공됩니다.

Toolkit 에디션은 커뮤니티 에디션을 포괄적 인 데이터 바인딩 레이어와 함께 인기 라이브러리 용 애플리케이션 및 통합을 구축하기위한 여러 UI 위젯으로 래핑하며 상업적으로 라이센스가 부여됩니다.


4
놀라운 툴킷이지만주의하십시오 : 무료가 아닙니다! 공개적으로 호스팅하거나 자체 제품 내에서 판매하려는 경우 라이선스를 구매하기를 원합니다 ( jsplumbtoolkit.com/purchase 참조 ).
Chris

50

svg로 선을 결합하는 것은 나에게 가치가 있었고 완벽하게 작동했습니다. 먼저 SVG (Scalable Vector Graphics)는 상호 작용 및 애니메이션을 지원하는 2 차원 그래픽을위한 XML 기반 벡터 이미지 형식입니다. SVG 이미지와 그 동작은 XML 텍스트 파일에 정의되어 있습니다. <svg>태그를 사용하여 HTML로 svg를 만들 수 있습니다 . Adobe Illustrator는 경로를 사용하여 복잡한 svg를 만드는 데 사용되는 최고의 소프트웨어 중 하나입니다.

한 줄을 사용하여 두 div를 결합하는 절차 :

  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>

    선 태그를 사용하면 지정된 두 점 (x1, y1)과 (x2, y2) 사이에 선을 그릴 수 있습니다. (참고로 w3schools를 방문하십시오.) 아직 지정하지 않았습니다. 라인 태그의 속성 (x1, y1, x2, y2)을 편집하기 위해 jQuery를 사용할 것이기 때문입니다.

  3. <script>태그 쓰기

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

    선택기를 사용하여 두 개의 div와 라인을 선택했습니다.

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

    jQuery position()메서드를 사용하면 요소의 현재 위치를 얻을 수 있습니다. 자세한 내용은 https://api.jquery.com/position/을 방문 하십시오 ( offset()방법도 사용할 수 있음 ).

이제 필요한 모든 위치를 얻었으므로 다음과 같이 선을 그릴 수 있습니다.

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

jQuery .attr()메서드는 선택한 요소의 속성을 변경하는 데 사용됩니다.

위 줄에서 우리가 한 것은 줄의 속성을

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

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

position()하나는 'left'이고 다른 하나는 'top'인 두 개의 값 을 반환하므로 객체 (여기서는 pos1 및 pos2)를 사용하여 .top 및 .left를 사용하여 쉽게 액세스 할 수 있습니다.

이제 라인 태그에는 두 점 사이에 선을 그리는 두 개의 별개의 좌표가 있습니다.

팁 : div에 필요에 따라 이벤트 리스너 추가

팁 : 스크립트 태그에 무엇이든 쓰기 전에 먼저 jQuery 라이브러리를 가져와야합니다.

JQuery와 통해 좌표를 추가 ... 그것은 다음과 같이 보일 것입니다

다음 스 니펫은 데모 목적으로 만 사용됩니다. 올바른 솔루션을 얻으려면 위의 단계를 따르십시오.

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


3
여러 질문에 동일한 답변을 복사하여 붙여 넣지 마십시오. 대신 개별 질문에 대한 답변을 사용자 정의하십시오.
Andy

2
z-index -1을 사용하여 svg를 배경에서 너비와 높이 100 %로 설정해야하지만 매력처럼 작동합니다.
스티븐


31
반대 투표자 여러분, 그 이유를 말씀해주십시오.이 답변이 두 질문에 모두 적용 가능할 것이기 때문에 두 질문에 대해 동일한 답변을 게시했습니다 ... 두 질문이 관련이있는 경우 해당 답변도 관련이있을 수 있습니다. . 나는 잘못된 일을하지 않았습니다 ...
Ani

6

며칠 전에도 동일한 요구 사항이있었습니다.

전체 너비높이 svg를 사용하여 모든 div 아래에 추가 하고 이러한 svg에 동적으로 을 추가했습니다 .

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

Safari 버전 12.0.1 (14606.2.104.1.1)에서 작동하지 않는 것 같습니다
balupton



2

최근에는 드래그 앤 드롭 구성 요소를 사용하고 이들을 연결하는 선이있는 간단한 웹 앱을 개발하려고했습니다. 이 두 가지 간단하고 놀라운 자바 스크립트 라이브러리를 발견했습니다.

  1. Plain Draggable : HTML / SVG 요소를 드래그 할 수있는 단순하고 고성능의 라이브러리입니다.
  2. 지시선 : 웹 페이지에 지시선을 그립니다 .


1



1

js-graph.it시작 안내서 에서 볼 수 있듯이이 사용 사례를 지원하며 연결이 겹치지 않는 드래그 요소를 지원합니다. 연결 편집 / 만들기를 지원하지 않는 것 같습니다. 더 이상 유지되지 않는 것 같습니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.