Tracer une ligne entre deux divs draggables

Oui je sais que ce genre de questions ont déjà été posées dans les liens suivants: Question 1 , Question 2 et Question 3 . Mais ma question est très différente des questions déjà posées.

ce que je veux est le suivant: j'ai deux divs draggables et ont un connecteur (une ligne droite) entre eux (dessiné avec SVG line). Quand je déplace ces divs draggable je dois déplacer un connecteur entre eux en conséquence. Ma question est plus similaire à la Question 3 , mais là, dans cette question, une fois qu'un utilisateur crée une connexion entre les divs, ces divs cessent d'être modulables, de sorte qu'ils ne se soucient pas de rafraîchir les connecteurs.

est-ce que quelqu'un a déjà rencontré un exemple ou une démonstration de travail de ce que je dis? Ou, quelqu'un pourrait-il me donner une idée de comment faire cela de manière optimale s'il vous plaît?

juste au cas où, j'utilise jQuery comme javascript framework (si cela vaut la peine de le savoir).

Merci beaucoup.

UPDATE 1

j'ai trouvé ce demo aussi, mais il fonctionne très très très mal, je dirais incorrectement.

80
demandé sur Community 2011-06-08 15:40:50

3 réponses

utilisez la bibliothèque jsplumb - best pour dessiner des lignes personnalisées sur la page web.

https://jsplumbtoolkit.com/demos.html

150
répondu Tomasz Kowalczyk 2015-08-11 14:13:35

joindre les lignes avec svgs valait le coup pour moi, et ça a fonctionné parfaitement... tout d'abord, Scalable Vector Graphics (SVG) est un format D'image vectorielle basé sur XML pour les graphiques bidimensionnels avec support pour 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 utilisés pour créer des SVG complexes en utilisant paths.

procédure à suivre joindre deux divs en utilisant une ligne:

  1. créer deux divs et leur donner n'importe quelle position que 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 le bien de l'explication, je suis en train de faire quelques inline style, mais il est toujours bon de faire un autre fichier css pour le style)

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

    étiquette 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 des écoles W3. nous ne les avons pas encore spécifiés. parce que nous utiliserons jQuery pour éditer les attributs (x1,y1,x2,y2) de la balise de ligne.

  3. dans <script> tag écrire

    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() permet d'obtenir la position actuelle d'un élément. Pour plus d'information, visitez https://api.jquery.com/position/ (vous pouvez utiliser offset() méthode trop)

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

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

Tout ce que nous avons fait dans above line est que nous avons changé les attributs de line 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, l'une "gauche" et l'autre "haut", nous pouvons facilement y accéder en utilisant .top et .gauche en utilisant les objets (ici pos1 et pos2)...

maintenant étiquette de ligne a deux coordonnées distinctes pour tracer la ligne entre deux points.

Conseil: ajouter des écouteurs d'événements comme vous avez besoin de divs

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

après ajouter les coordonnées par JQuery ... Il ressemblera à quelque chose comme ceci

L'extrait suivant est à des fins de démonstration seulement, s'il vous plaît suivre les étapes ci-dessus pour obtenir la solution correcte

<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>
29
répondu Ani 2018-03-26 17:13:28

j'ai également le même exigence quelques jours en arrière

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

la Caisse de la façon dont je l'ai fait ici à l'aide de 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
répondu Nadir Laskar 2017-06-07 06:46:09