Проведення сполучної лінії між двома елементами [закрито]


106

Як я можу намалювати лінію між двома або більше елементами, щоб з'єднати їх? Будь-яка комбінація HTML / CSS / JavaScript / SVG / Canvas є чудовою.

Якщо ваша відповідь підтримує будь-яке з них, то згадайте це:

  • перетягуються елементи
  • перетягувані / редаговані з'єднання
  • уникнення перекриття елементів

Це питання було оновлено, щоб закріпити численні його варіанти .

Відповіді:


164

jsPlumb - це доступна опція, яка підтримує перетягування, як видно з її численних демонстраційних демонстрацій , включаючи демонстраційну схему блок-схеми .

Він доступний у безкоштовній спільноті та платній версії інструментарію.

Видання Toolkit охоплює видання спільноти всеосяжним шаром прив'язки даних, а також декількома віджетами інтерфейсу користувача для побудови додатків та інтеграцій для популярних бібліотек і має комерційну ліцензію.


4
Дивовижний інструментарій, але будьте попереджені: це не безкоштовно! Вони хочуть, щоб ви придбали ліцензію, якщо ви плануєте публічно розміщувати рекламу чи продавати в межах своєї власної продукції (див. Jsplumbtoolkit.com/purchase ).
Кріс

50

З'єднання ліній зі svgs було вагомим знімком для мене, і воно спрацювало чудово ... Перш за все, масштабована векторна графіка (SVG) - це формат векторного зображення на основі XML для двовимірної графіки з підтримкою інтерактивності та анімації. Зображення SVG та їх поведінка визначаються у текстових файлах XML. ви можете створити svg в HTML за допомогою <svg>тегу. Adobe Illustrator - одне з найкращих програм, що використовуються для створення складних svgs за допомогою шляхів.

Процедура приєднання двох дівок за допомогою рядка:

  1. створіть дві діви і надайте їм будь-яке положення, як вам потрібно

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

    (задля пояснення я роблю деякі вбудовані стилі, але завжди добре зробити окремий файл css для стилізації)

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

    Тег лінії дозволяє нам провести лінію між двома вказаними точками (x1, y1) та (x2, y2). (для довідкового відвідування w3schools.) ми їх ще не вказали. тому що ми будемо використовувати jQuery для редагування атрибутів (x1, y1, x2, y2) тегів рядка.

  3. в <script>тег написати

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

    Я використовував селектори для вибору двох дівок та рядків ...

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

    position()Метод jQuery дозволяє нам отримати поточне положення елемента. Для отримання додаткової інформації відвідайте https://api.jquery.com/position/ (ви також можете використовувати offset()метод)

Тепер, коли ми отримали всі потрібні нам позиції, ми можемо провести лінію наступним чином ...

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

.attr()Метод jQuery використовується для зміни атрибутів вибраного елемента.

Все, що ми зробили у верхньому рядку, - це те, що ми змінили атрибути рядка з

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

до

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

оскільки position()повертає два значення, одне "ліве" та інше "верхнє", ми можемо легко отримати доступ до них за допомогою .top та .left за допомогою об'єктів (тут pos1 та pos2) ...

Тепер тег рядка має дві чіткі координати, щоб провести лінію між двома точками.

Порада: додайте слухачів подій, як вам потрібно, щоб діви

Порада: переконайтесь, що ви імпортуєте бібліотеку jQuery спочатку, перш ніж щось писати в тег сценарію

Після додавання координат через JQuery ... Це буде виглядати приблизно так

Наступний фрагмент призначений лише для демонстрації, виконайте кроки вище, щоб отримати правильне рішення

<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
Будь ласка, не копіюйте та не вставляйте однакову відповідь на кілька запитань. Натомість налаштуйте відповіді на окремі запитання.
Енді

2
Мені потрібно покласти svg на ширину та висоту 100% у фоновому режимі, використовуючи z-індекс -1, але він працює як шарм.
Стівен

4
Ця відповідь скопійована з stackoverflow.com/questions/19382872/…
Damjan Pavlica

31
Першочергові, будь ласка, прокоментуйте причину цього ... Я опублікував однакові відповіді на обидва питання, тому що я впевнений, що ця відповідь стосується обох питань ... Якщо два питання є актуальними, то їх відповіді також можуть бути актуальними .. Я нічого неправильного не зробив ...
Ані

6

У мене також була така ж вимога кілька днів тому

Я використовував svg повної ширини та висоти і додав його нижче всіх моїх divs та додав рядки до цих svg динамічно.

Перевірте, як я це робив тут, використовуючи 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);
});

Здається, не працює над версією Safari 12.0.1 (14606.2.104.1.1)
balupton



2

Нещодавно я спробував розробити простий веб-додаток, який використовує компоненти перетягування та перетягування. Я натрапив на ці дві прості та дивовижні бібліотеки javascript:

  1. Звичайний перетягувач : проста та високопродуктивна бібліотека, яка дозволяє перетягувати HTML / SVG елемент.
  2. Лінія лідерів : намалюйте лінійку лідерів на своїй веб-сторінці


1


1

Cytoscape підтримує це на прикладі архітектури, який підтримує перетягуючі елементи.

Для створення з’єднань є розширення крайових ручок . Він ще не підтримує редагування наявних з'єднань. Питання.

Для редагування форм з'єднання існує розширення для редагування краю . Демо

Розширення редагування-редагування здається багатообіцяючим, однак демонстрації поки немає.


1

js-graph.it підтримує цей випадок використання, як видно з його посібника для початку роботи , підтримуючи перетягуючі елементи без накладання з'єднань. Схоже, він не підтримує редагування / створення з'єднань. Здається, це більше не підтримується.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.