web-dev-qa-db-fra.com

Tracer une ligne de liaison entre deux éléments

Comment puis-je (ou quels outils sont disponibles) pour tracer une ligne entre deux ou plusieurs éléments pour les connecter? Toute combinaison de HTML/CSS/JavaScript/SVG/Canvas est acceptable.

Si votre réponse corrobore l’une de ces questions, mentionnez-la:

  • éléments déplaçables
  • connexions déplaçables/modifiables
  • éviter les chevauchements d'éléments

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

86
Bakhtiyor

jsPlumb est une option disponible qui prend en charge le glisser-déposer, comme en témoignent ses nombreuses démos , y compris le Organigramme démo .

Il est disponible dans une édition communautaire gratuite et une édition payante de la boîte à outils.

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

155
Tomasz Kowalczyk

Assembler des lignes avec svgs valait la peine, et tout fonctionnait parfaitement ....__ tout d’abord, Scalable Vector Graphics (SVG) est un format d’image vectorielle basé sur XML destiné aux graphiques bidimensionnels prenant en charge l’interactivité et 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 la balise <svg>. Adobe Illustrator est l’un des meilleurs logiciels permettant de créer un fichier svgs complexe à l’aide de chemins.

Procédure pour joindre deux divs en utilisant 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>
    

    (Par souci d’explication, je fais un peu de 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ées. car nous allons utiliser jQuery pour éditer les attributs (x1, y1, x2, y2) de la balise line.

  3. en écriture <script>

    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 méthode jQuery position() 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 méthode offset())

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

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

la méthode jQuery .attr() permet de modifier les attributs de l'élément sélectionné. 

Tout ce que nous avons fait dans la ligne ci-dessus 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 "gauche" et une autre "haut", nous pouvons facilement y accéder en utilisant .top et .left en utilisant les objets (ici pos1 et pos2) ... 

Maintenant, l’étiquette de ligne a deux coordonnées distinctes pour tracer une ligne entre deux points.

Astuce: ajoutez des écouteurs d'événements en fonction des divs

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

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

_ {L'extrait suivant sert uniquement de démonstration, veuillez suivre les étapes ci-dessus pour obtenir la solution appropriée}

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

34
Ani

J'ai aussi la même exigence quelques jours en arrière

J'ai utilisé un largeur et hauteursvg complets en-dessous de tous mes divs et j'ai ajouté lignes dynamiquement à ces svg.

Commander la façon dont 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);
});
4
Nadir Laskar
1
balupton

Cytoscape supporte cela avec son Exemple d'architecture qui supporte les éléments glissés.

Pour créer des connexions, il y a edgehandles extension. Il ne supporte pas encore l'édition des connexions existantes.Question.

Pour éditer les formes de connexion, il existe l’extension Edge-édition . Démo.

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

1
balupton

Raphaël soutient cela, avec son exemple Graffle .

Cette réponse est basée sur Awais Akhtaranswer , et Vaibhav Jainanswer .

0
balupton

VisJS supporte cela avec son exemple Arrows , qui supporte les éléments déplaçables.

Je n'ai pas pu trouver d'exemple qui prenne en charge les connexions modifiables.

0
balupton

GoJS le supporte, avec son exemple de graphique d'état , qui prend en charge le glisser-déposer d'éléments et la modification de connexions.

Cette réponse est basée sur (Walter Northwoods ' } _ réponse .

0
balupton

JointJS/Rappid prend en charge ce cas d'utilisation avec son exemple Kitchensink qui prend en charge le glisser-déposer d'éléments et le repositionnement de connexions. Il a de nombreux exemples.

Cette réponse est basée sur de Vainbhav Jainanswer .

0
balupton

js-graph.it prend en charge ce cas d'utilisation, comme le montre son guide getting started , prenant en charge le déplacement d'éléments sans chevauchement de connexion. Ne semble pas supporter la modification/création de connexions. On dirait que ça ne se maintient plus.

0
balupton

mxGraph - utilisé par draw.io - prend en charge ce cas d'utilisation, avec son exemple Grapheditor . Documentation.Exemples.

Cette réponse est basée sur de Vainbhav Jainanswer .

0
balupton