Tracciare una linea di collegamento tra due elementi [chiuso]


106

Come posso disegnare una linea tra due o più elementi per collegarli? Qualsiasi combinazione di HTML / CSS / JavaScript / SVG / Canvas va bene.

Se la tua risposta supporta uno di questi, menzionalo:

  • elementi trascinabili
  • connessioni trascinabili / modificabili
  • evitamento della sovrapposizione degli elementi

Questa domanda è stata aggiornata per consolidarne le numerose variazioni .

Risposte:


164

jsPlumb è un'opzione disponibile che supporta il drag and drop, come si vede dalle sue numerose demo , inclusa la demo del diagramma di flusso .

È disponibile in un'edizione Community gratuita e in un'edizione Toolkit a pagamento.

L'edizione Toolkit racchiude l'edizione Community con un livello di associazione dati completo, oltre a diversi widget dell'interfaccia utente per la creazione di applicazioni e integrazioni per le biblioteche più diffuse ed è concessa in licenza commerciale.


4
Toolkit incredibile ma attenzione: non è gratuito! Vogliono che tu acquisti una licenza se intendi ospitare pubblicamente o vendere all'interno dei tuoi prodotti (vedi jsplumbtoolkit.com/purchase ).
Chris

50

Unire le linee con svgs è valsa la pena per me, e ha funzionato perfettamente ... prima di tutto, Scalable Vector Graphics (SVG) è un formato di immagine vettoriale basato su XML per grafica bidimensionale con supporto per interattività e animazione. Le immagini SVG e il loro comportamento sono definiti in file di testo XML. puoi creare un svg in HTML usando <svg>tag. Adobe Illustrator è uno dei migliori software utilizzati per creare un SVG complesso utilizzando i percorsi.

Procedura per unire due div utilizzando una riga:

  1. crea due div e dai loro la posizione di cui hai bisogno

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

    (per motivi di spiegazione sto eseguendo uno stile inline ma è sempre bene creare un file css separato per lo stile)

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

    Il tag di linea ci consente di tracciare una linea tra due punti specificati (x1, y1) e (x2, y2). (per una consultazione visita w3schools.) non li abbiamo ancora specificati. perché useremo jQuery per modificare gli attributi (x1, y1, x2, y2) del tag di riga.

  3. nella <script>scrittura di tag

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

    Ho usato i selettori per selezionare i due div e la linea ...

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

    Il position()metodo jQuery ci permette di ottenere la posizione corrente di un elemento. Per maggiori informazioni, visita https://api.jquery.com/position/ (puoi usare offset()anche il metodo)

Ora che abbiamo ottenuto tutte le posizioni di cui abbiamo bisogno possiamo tracciare la linea come segue ...

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

Il .attr()metodo jQuery viene utilizzato per modificare gli attributi dell'elemento selezionato.

Tutto ciò che abbiamo fatto nella riga sopra è stato modificato gli attributi della riga da

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

per

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

poiché position()restituisce due valori, uno 'left' e l'altro 'top', possiamo accedervi facilmente usando .top e .left usando gli oggetti (qui pos1 e pos2) ...

Ora il tag di linea ha due coordinate distinte per tracciare la linea tra due punti.

Suggerimento: aggiungi i listener di eventi di cui hai bisogno ai div

Suggerimento: assicurati di importare la libreria jQuery prima di scrivere qualsiasi cosa nel tag script

Dopo aver aggiunto le coordinate tramite JQuery ... Assomiglierà a questo

Il seguente frammento è solo a scopo dimostrativo, segui i passaggi precedenti per ottenere la soluzione corretta

<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
Si prega di non copiare e incollare la stessa risposta a più domande. Personalizza invece le risposte alle singole domande.
Andy

2
Devo mettere lo svg in larghezza e altezza al 100% in background usando z-index -1 ma funziona a meraviglia.
Steven

4
Questa risposta è stata copiata da stackoverflow.com/questions/19382872/…
Damjan Pavlica,

31
Downvoters, per favore commenta il motivo per farlo ... Ho pubblicato le stesse risposte per entrambe le domande perché sono sicuro che questa risposta sia applicabile a entrambe le domande ... Se due domande sono rilevanti, allora anche le loro risposte possono essere rilevanti .. Non ho fatto nulla di sbagliato ...
Ani

6

Ho anche avuto lo stesso requisito pochi giorni fa

Ho usato uno svg a larghezza e altezza completa e l'ho aggiunto sotto tutti i miei div e ho aggiunto linee a questi svg in modo dinamico.

Guarda come l'ho fatto qui usando 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);
});

Non sembra funzionare su Safari versione 12.0.1 (14606.2.104.1.1)
balupton



2

Recentemente, ho provato a sviluppare una semplice app web che utilizza componenti drag and drop e dispone di linee che li collegano. Mi sono imbattuto in queste due librerie javascript semplici e sorprendenti:

  1. Plain Draggable : libreria semplice e ad alte prestazioni per consentire il trascinamento di elementi HTML / SVG.
  2. Linea guida : traccia una linea guida nella tua pagina web


1



1

js-graph.it supporta questo caso d'uso, come si vede dalla sua guida introduttiva , che supporta il trascinamento di elementi senza sovrapposizioni di connessione. Non sembra che supporti la modifica / la creazione di connessioni. Non sembra più essere mantenuto.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.