Проведение линии между двумя перетаскиваемыми дивами
Да я знаю, что такого рода вопросы были заданы ранее в следующих ссылках: Вопрос 1, Вопрос 2 и вопрос 3. Но мой вопрос сильно отличается от уже заданных вопросов.
Я хочу следующее: У меня есть два перетаскиваемых дива и есть разъем (прямая линия) между ними (нарисованная с помощью линии SVG). Когда я перемещаю эти перетаскиваемые дивы, мне нужно переместить разъем между ними соответственно. Мой вопрос больше похож на вопрос 3, но есть в этом вопрос: как только пользователь создает соединение между divs, эти divs перестают быть перетаскиваемыми, поэтому они не заботятся об обновлении разъемов.
кто-нибудь когда-нибудь встречал какой-либо рабочий пример или демонстрацию того, что я говорю? Или, может кто-нибудь дать мне какие-либо идеи о том, как сделать это оптимальным образом, Пожалуйста?
на всякий случай, я использую jQuery в качестве JavaScript-фреймворка (если это стоит знать).
Спасибо большое.
обновление 1
и демо также, но это работает очень и очень плохо, я бы сказал неправильно.
3 ответа:
соединение линий с svgs стоило мне выстрела, и это сработало отлично... прежде всего, Scalable Vector Graphics (SVG)-это формат векторных изображений на основе XML для двумерной графики с поддержкой интерактивности и анимации. Изображения SVG и их поведение определяются в текстовых файлах XML. вы можете создать svg в HTML с помощью
<svg>
тег. Adobe Illustrator является одним из лучших программ, используемых для создания сложных svgs с использованием путей.процедура соединения двух дивов с помощью линия:
создайте два дива и дайте им любую позицию, как вам нужно
<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 для укладки)
<svg><line id="line1"/></svg>
Line tag позволяет нам провести линию между двумя указанными точками (x1,y1) и (x2,y2). (для справки посетите w3schools.) мы их пока не уточнили. потому что мы будем использовать jQuery для редактирования атрибутов (x1,y1,x2,y2) тега line.
на
<script>
tag writeline1 = $('#line1'); div1 = $('#div1'); div2 = $('#div2');
я использовал селекторы для выбора двух дивов и линии...
var pos1 = div1.position(); var pos2 = div2.position();
jQuery
position()
метод позволяет получить текущее положение элемента. Для получения дополнительной информации посетите https://api.jquery.com/position/ (вы можете использоватьoffset()
метод тоже)теперь как мы получили все позиции, которые нам нужны, мы можем нарисовать линию следующим образом...
line1 .attr('x1', pos1.left) .attr('y1', pos1.top) .attr('x2', pos2.left) .attr('y2', pos2.top);
jQuery
.attr()
метод используется для изменения атрибутов выбранного элемента.все, что мы сделали в вышеуказанной строке, это мы изменили атрибуты строки из
x1 = 0 y1 = 0 x2 = 0 y2 = 0
до
x1 = pos1.left y1 = pos1.top x2 = pos2.left y2 = pos2.top
как
position()
возвращает два значения, один "левый" и другой "верхний", мы можем легко получить к ним доступ с помощью .верх и. влево с помощью объектов (здесь pos1 и pos2) ...теперь тег линии имеет два различные координаты, чтобы провести линию между двумя точками.
совет: добавить прослушиватели событий, как вам нужно divs
совет: убедитесь, что вы импортируете библиотеку 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>
у меня тоже такое же требование несколько дней назад
я использовал полный ширина и высота svg и добавил его ниже всех моих дивов и добавил строки к этим 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); });