2011-06-08 28 views
76

Sí, sé que este tipo de preguntas se han formulado anteriormente en los siguientes enlaces: Question 1, Question 2 y Question 3. Pero mi pregunta es bastante diferente de las preguntas ya hechas.Trazando una línea entre dos divisores arrastrables

Lo que quiero es lo siguiente: Tengo dos divs que se pueden arrastrar y tengo un conector (una línea recta) entre ellos (dibujado con la línea SVG). Cuando muevo estos divs que se pueden arrastrar, necesito mover un conector entre ellos en consecuencia. Mi pregunta es más similar al Question 3, pero en esa pregunta, una vez que un usuario crea una conexión entre los divs, los divs dejan de ser arrastrables, por lo que no les importa refrescar los conectores.

¿Alguien ha conocido alguna vez algún ejemplo de funcionamiento o demo de lo que estoy diciendo? O bien, ¿alguien podría darme alguna idea de cómo hacerlo de forma óptima, por favor?

Por las dudas, estoy usando jQuery como marco de JavaScript (si vale la pena saberlo).

Muchas gracias.

ACTUALIZA 1

He encontrado que esto demo también, pero funciona muy, muy mal, yo diría de forma incorrecta.

+0

consigo alerta antivirus con esa demo-link – Antti

Respuesta

146

Utilice jsPlumb - la mejor biblioteca para dibujar líneas personalizadas en la página web.

https://jsplumbtoolkit.com/demos.html

+0

muy potente biblioteca, creo Trataré de explorarlo y usarlo. Creo que es exactamente lo que estaba buscando. – Bakhtiyor

+7

Impresionante ... ¡Estas "cosas que hacen las personas" no tienen límite! – heltonbiker

+1

Esta biblioteca es irreal. No puedo creer lo increíble que funciona. ¡Guauu! – crush

24

líneas que unen con svgs valía la pena intentarlo para mí, y funcionó perfectamente ... en primer lugar, gráficos vectoriales escalables (SVG) es un formato de imagen vectorial basado en XML para dos dimensiones gráficos con soporte para interactividad y animación. Las imágenes SVG y sus comportamientos se definen en archivos de texto XML. puedes crear un svg en HTML usando la etiqueta <svg>. Adobe Illustrator es uno de los mejores software utilizados para crear un svgs complejo utilizando rutas.

Procedimiento para unir dos divs usando una línea:

  1. crear dos divs y darles cualquier posición que necesite

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

    (por el bien de la explicación que estoy haciendo algo más de estilo en línea pero siempre es bueno hacer un archivo css separada para el peinado)

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

    La etiqueta de línea nos permite trazar una línea entre dos puntos especificados (x1, y1) y (x2, y2). (para una visita de referencia de w3schools.) aún no los hemos especificado. porque usaremos jQuery para editar los atributos (x1, y1, x2, y2) de la etiqueta de línea.

  3. en <script> etiqueta de escritura

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

    que utilizan selectores para seleccionar los dos divs y la línea ...

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

    jQuery position() método permite obtener la posición actual de un elemento.Para obtener más información, visite https://api.jquery.com/position/ (se puede utilizar el método offset() demasiado)

Ahora bien, como hemos obtenido todas las posiciones que necesitamos podemos sacar la línea de la siguiente manera ...

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

jQuery .attr() método se usa para cambiar los atributos del elemento seleccionado.

Todo lo que hicimos en la línea anterior es que cambiamos los atributos de la línea de

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

a

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

como position() devuelve dos valores, uno y otro 'top' 'izquierda', podemos acceda fácilmente usando .top y .left usando los objetos (aquí pos1 y pos2) ...

Ahora la etiqueta de línea tiene dos coordenadas distintas para dibujar la línea entre dos puntos.

Consejo: añadir detectores de eventos como sea necesario para divs

Consejo: asegúrese de importar librería jQuery primero antes de escribir cualquier cosa en etiqueta script

Después de la adición de coordina a través de jQuery ... Es se verá algo como esto

siguiente fragmento es para propósitos de demostración solamente, por favor siga los pasos de arriba para obtener la solución correcta

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

+2

No copie y pegue la misma respuesta a varias preguntas. En cambio, personalice las respuestas a las preguntas individuales. – Andy

+2

Necesito poner el svg en ancho y alto 100% en el fondo usando z-index -1 pero funciona como un amuleto. – steven

+2

Esta respuesta se copió de http://stackoverflow.com/questions/19382872/how-to-connect-html-divs-with -lines –

2

También tengo el mismo requisito pocos días atrás

He utilizado un total ancho y alturaSVG y añadió que a continuación todos mis divs y añadió líneas a estos svg dinámicamente.

obtener de la forma en que lo hice aquí 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); 
});