Tracer une ligne de connexion entre deux éléments [fermé]

106

Comment puis-je dessiner une ligne entre deux ou plusieurs éléments pour les relier? Toute combinaison de HTML / CSS / JavaScript / SVG / Canvas convient.

Si votre réponse prend en charge l'un de ces éléments, mentionnez-le:

  • éléments déplaçables
  • connexions déplaçables / modifiables
  • évitement du chevauchement des éléments

Cette question a été mise à jour pour en consolider les nombreuses variantes .

Bakhtiyor
la source

Réponses:

164

jsPlumb est une option disponible qui prend en charge le glisser-déposer, comme le montrent ses nombreuses démos , y compris la démo de Flowchart .

Il est disponible dans une édition communautaire gratuite et une édition payante de Toolkit.

L'édition Toolkit englobe l'édition Community avec une couche de liaison de données complète, ainsi que plusieurs widgets d'interface utilisateur pour créer des applications et des intégrations pour des bibliothèques populaires, et est sous licence commerciale.

Tomasz Kowalczyk
la source
4
Boîte à outils incroyable mais attention: ce n'est pas gratuit! Ils veulent que vous achetiez une licence si vous avez l'intention d'héberger publiquement ou de vendre vos propres produits (voir jsplumbtoolkit.com/purchase ).
Chris
50

Joindre des lignes avec des svgs valait le coup pour moi, et cela a parfaitement fonctionné ... Tout d'abord, Scalable Vector Graphics (SVG) est un format d'image vectorielle basé sur XML pour les graphiques en deux dimensions avec prise en charge de l'interactivité et de l'animation. Les images SVG et leurs comportements sont définis dans des fichiers texte XML. vous pouvez créer un svg en HTML en utilisant une <svg>balise. Adobe Illustrator est l'un des meilleurs logiciels utilisés pour créer des svgs complexes à l'aide de chemins.

Procédure pour joindre deux div à l'aide d'une ligne:

  1. créez deux divs et donnez-leur la position dont vous avez besoin

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

    (pour des raisons d'explication, je fais du style en ligne mais il est toujours bon de créer un fichier css séparé pour le style)

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

    La balise de ligne nous permet de tracer une ligne entre deux points spécifiés (x1, y1) et (x2, y2). (pour une visite de référence w3schools.) nous ne les avons pas encore spécifiés. car nous utiliserons jQuery pour éditer les attributs (x1, y1, x2, y2) de la balise de ligne.

  3. en <script>écriture de balise

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

    J'ai utilisé des sélecteurs pour sélectionner les deux divs et la ligne ...

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

    La position()méthode jQuery nous permet d'obtenir la position actuelle d'un élément. Pour plus d'informations, visitez https://api.jquery.com/position/ (vous pouvez également utiliser la offset()méthode)

Maintenant que nous avons obtenu toutes les positions dont nous avons besoin, nous pouvons tracer la ligne comme suit ...

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

jQuery .attr() méthode est utilisée pour modifier les attributs de l'élément sélectionné.

Tout ce que nous avons fait dans la ligne ci-dessus, c'est que nous avons changé les attributs de la ligne de

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

à

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

comme position() renvoie deux valeurs, une 'left' et l'autre 'top', on peut facilement y accéder en utilisant .top et .left en utilisant les objets (ici pos1 et pos2) ...

L'étiquette de ligne a maintenant deux coordonnées distinctes pour tracer une ligne entre deux points.

Astuce: ajoutez des écouteurs d'événements selon vos besoins

Astuce: assurez-vous d'importer la bibliothèque jQuery avant d'écrire quoi que ce soit dans la balise de script

Après avoir ajouté des coordonnées via JQuery ... Cela ressemblera à quelque chose comme ça

L'extrait suivant est uniquement à des fins de démonstration, veuillez suivre les étapes ci-dessus pour obtenir la bonne 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>

Ani
la source
3
Veuillez ne pas copier et coller la même réponse à plusieurs questions. Personnalisez plutôt les réponses aux questions individuelles.
Andy
2
Je dois mettre le svg à la largeur et à la hauteur de 100% en arrière-plan en utilisant z-index -1 mais cela fonctionne comme un charme.
steven
4
Cette réponse est copiée de stackoverflow.com/questions/19382872/…
Damjan Pavlica
31
Les votants négatifs, veuillez commenter la raison de le faire ... J'ai publié les mêmes réponses pour les deux questions car je suis sûr que cette réponse est applicable aux deux questions ... Si deux questions sont pertinentes, alors leurs réponses peuvent également l'être. . Je n'ai rien fait de mal ...
Ani
6

J'ai également eu la même exigence il y a quelques jours

J'ai utilisé un svg pleine largeur et hauteur et l'ai ajouté sous toutes mes divs et ajouté des lignes à ces svg dynamiquement.

Découvrez comment je l'ai fait ici en utilisant 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);
});
Nadir Laskar
la source
Ne semble pas fonctionner sur Safari Version 12.0.1 (14606.2.104.1.1)
balupton
2

Récemment, j'ai essayé de développer une application Web simple qui utilise des composants glisser-déposer et des lignes les reliant. Je suis tombé sur ces deux bibliothèques javascript simples et étonnantes:

  1. Plain Draggable : bibliothèque simple et performante pour permettre le glissement des éléments HTML / SVG.
  2. Ligne de repère: tracez une ligne de repère dans votre page Web
Chérubins
la source
1

D3 a des centaines d'exemples , dont certains conviennent à cette question.

Exemples sans glisser-déposer, qui sont corrigés:

Exemples sans glisser-déposer, interactifs:

Exemples avec glisser-déposer:

Cette réponse est basée sur la réponse de Glenn Dayton .

balupton
la source
1

Cytoscape prend en charge cela avec son exemple d'architecture qui prend en charge le glissement d'éléments.

Pour créer des connexions, il existe l' extension des poignées de bord . Il ne prend pas encore en charge la modification des connexions existantes. Question.

Pour modifier les formes de connexion, il existe l' extension d' édition des bords . Démo.

L' extension edit-editation semble prometteuse, cependant il n'y a pas encore de démo.

balupton
la source
1

js-graph.it prend en charge ce cas d'utilisation, comme le montre son guide de démarrage , prenant en charge le glissement d'éléments sans chevauchement de connexion. Il ne semble pas qu'il prenne en charge l'édition / la création de connexions. Cela ne semble plus être maintenu.

balupton
la source