Проведение соединительной линии между двумя элементами [закрыто]

106

Как я могу провести линию между двумя или более элементами, чтобы соединить их? Подойдет любая комбинация HTML / CSS / JavaScript / SVG / Canvas.

Если ваш ответ поддерживает что-либо из этого, укажите это:

  • перетаскиваемые элементы
  • перетаскиваемые / редактируемые соединения
  • предотвращение перекрытия элементов

Этот вопрос был обновлен, чтобы объединить его многочисленные варианты .

Бахтиёр
источник

Ответы:

164

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

Он доступен в бесплатной версии Community и платной версии Toolkit.

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

Томаш Ковальчик
источник
4
Замечательный набор инструментов, но имейте в виду: это не бесплатно! Они хотят, чтобы вы купили лицензию, если вы собираетесь размещать на публичном сервере или продавать в рамках своих собственных продуктов (см. Jsplumbtoolkit.com/purchase ).
Крис
51

Соединение строк с svgs стоило мне попыток, и это сработало отлично ... во-первых, Scalable Vector Graphics (SVG) - это формат векторного изображения на основе XML для двухмерной графики с поддержкой интерактивности и анимации. Изображения SVG и их поведение определяются в текстовых файлах XML. вы можете создать SVG в HTML с помощью <svg>тега. Adobe Illustrator - одно из лучших программ, используемых для создания сложных SVG с использованием путей.

Процедура соединения двух div с помощью строки:

  1. создайте два div и дайте им любую позицию, как вам нужно

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

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

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

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

    Я использовал селекторы, чтобы выбрать два div и строку ...

    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

as position()возвращает два значения, одно 'left' и другое 'top', мы можем легко получить к ним доступ, используя .top и .left, используя объекты (здесь pos1 и pos2) ...

Теперь у линейного тега есть две разные координаты, чтобы провести линию между двумя точками.

Совет: добавьте прослушиватели событий по мере необходимости в div

Совет: убедитесь, что вы импортируете библиотеку jQuery, прежде чем писать что-либо в теге script

После добавления координат через 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-index -1, но он работает как шарм.
Стивен
4
Этот ответ скопирован с stackoverflow.com/questions/19382872/…
Дамьян Павлика
31
Сторонники отрицательного голосования, прокомментируйте причину этого ... Я отправил одинаковые ответы на оба вопроса, потому что уверен, что этот ответ применим к обоим вопросам ... Если два вопроса актуальны, то их ответы также могут быть актуальными ..
Ани
6

У меня тоже было такое же требование несколько дней назад

Я использовал svg полной ширины и высоты и добавил его под всеми своими div и добавил строки в эти 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. Plain Draggable : простая и высокопроизводительная библиотека, позволяющая перетаскивать элементы HTML / SVG.
  2. Линия выноски: нарисуйте линию выноски на своей веб-странице.
Херувимы
источник
1

В D3 есть сотни примеров , некоторые из которых подходят для этого вопроса.

Примеры без перетаскивания, которые исправлены:

Примеры без перетаскивания, интерактивные:

Примеры с перетаскиванием:

Этот ответ основан на ответе Гленна Дейтона .

Балуптон
источник
1

Cytoscape поддерживает это в своем примере архитектуры, который поддерживает перетаскивание элементов.

Для создания соединений имеется удлинитель кромочных ручек . Он еще не поддерживает редактирование существующих подключений. Вопрос.

Для редактирования форм соединений есть расширение для редактирования кромок . Демо.

Расширение редактирования-редактирования кажется многообещающим, однако демо пока нет.

Балуптон
источник
1

js-graph.it поддерживает этот случай использования, как это видно по его руководству по началу работы , поддержка перетаскивания элементов без подключения наложений. Не похоже, что он поддерживает редактирование / создание соединений. Похоже, он больше не поддерживается.

Балуптон
источник