Нарисовать стрелку между списками

Есть ли способ динамически рисовать стрелку между двумя выделенными элементами списка?

Итак, если бы я зависал над "Item 2", он сделал бы это (но прямую стрелку):

Item 1            Highlight 3
Item 2-----\      Highlight 1
Item 3      ----->Highlight 2

Это код из ответа, который я получил здесь несколько минут назад:

Выделите элемент в двух списках при наведении курсора мыши

$(".list1 li, .list2 li").hover(function () {
    var n = this.id.substr(2);
    $("#qq" + n + ", #aa" + n).toggleClass("highlight");
});

jsfiddle: http://jsfiddle.net/e37Yg/1/

<ul class="list1">
    <li id="qq1">sdfsdv</li>
    <li id="qq2">bnvnvb</li>
    <li id="qq3">nmnutymnj7</li>
    <li id="qq4">cvbc</li>
    <li id="qq5">45tsgd</li>
</ul>

<ul class="list2">
    <li id="aa3">fgtbrtgb</li>
    <li id="aa1">vbn xgbn</li>
    <li id="aa5">vdgver</li>
    <li id="aa4">asdasdv</li>
    <li id="aa2">nvfbnfn</li>
</ul>

Ответ 1

Вам не нужно использовать 2D-чертеж здесь. Проверьте это: http://jsfiddle.net/vjYuW/ Я только разветкил и обновил скрипку, которую вы разместили выше.

Вот основной код, он обрабатывает 3 DIVs 1 пиксель шириной или высоким для рисования линий:

HTML:


...left list...
<div id="segment1" class="hline"></div>
<div id="segment2" class="vline"></div>
<div id="segment3" class="hline"></div>
...right list...

CSS


... formatting for ULs here, both have to be float:left...

.highlight { background-color: red; }

.hline {    
    display:block;
    position:relative;
    float:left;
    height: 1px;
    width: 7em;  
}

.vline {
    display:block;
    position:relative;
    float:left;
    height: 1px;
    width: 1px;    
}

JavaScript:


$(".list1 li, .list2 li").hover(function () {
    var n = this.id.substr(2);
    var leftY = $('#qq' + n).position().top;
    var rightY = $('#aa' + n).position().top;
    var H = Math.abs(rightY-leftY);
    if (H == 0) H = 1;
    $('#segment1').css('top',leftY+'px');
    $('#segment3').css('top',rightY+'px');
    $('#segment2').css('top',Math.min(leftY,rightY)+'px');
    $('#segment2').css('height',H+'px');
    $("#qq" + n + ", #aa" + n + ",#segment1,#segment2,#segment3").toggleClass("highlight");
});

Примечание: вам, вероятно, придется немного подстроить его для поддержки всех браузеров - я не проверял IE6 и Co.

Ответ 2

Для этого вы можете использовать элемент HTML5 canvas.

Я не уверен, что это лучший способ сделать это, но я возился и получил этот.

Что я сделал, сначала я включил списки в div. div имеет CSS с относительной позицией. Это так, когда вы получаете позицию с помощью jQuery, это даст положение относительно этого. Затем я положил холст перед списками и отключил на нем события указателя. Я также добавил что-то, чтобы настроить высоту холста на высоту списков. Затем я добавил еще одного обработчика для зависания. Когда вы наводите на него курсор, он нарисует стрелку, и когда вы наведете курсор, он очистит полотно.

Нарисовать стрелку достаточно просто. Сначала он получает позиции предметов. Затем он рисует линию и использует некоторую математику для ориентации стрелки. Получить позиции довольно просто. Для правильного списка вы можете просто использовать метод position. Для левого списка я создал временный span и добавил его в элемент списка, а затем получил его положение.

Ответ 3

Я думаю, что для чего-то подобного вы можете использовать стороннюю библиотеку рисования, такую ​​как Vector Draw Library.

Вы можете загрузить библиотеку по ссылке и добавить ее в свое приложение. Тогда:

Включите его на свою страницу:

<script type="text/javascript" src="wz_jsgraphics.js"></script>

Затем добавьте функцию зависания:

$(".list1 li, .list2 li").hover(function () {
  var n = this.id.substr(2);
  $("#qq" + n + ", #aa" + n).toggleClass("highlight");

  //canvas is your drawing div
  var jg = new jsGraphics("canvas");
  jg.drawLine($("#qq" + n).offset().left + 30, $("#qq" + n).offset().top , $("#aa" + n).offset().left, $("#aa" + n).offset().top );
  jg.paint();

Обратите внимание, что вам нужно будет написать код для удаления строки в функции наведения, иначе, как только она будет нарисована, она останется. Кроме того, я использую offset() для вычисления позиции элементов в списке. Это должно работать, но вам, возможно, придется немного подкорректировать, чтобы он выглядел правильно.

Вышеприведенный код работает, но не завершен. Возможно, вторая функция в наведении может вызывать clear() на холсте. Холст - это включающий div, который включает два списка.

Ответ 4

<script src='www.walterzorn.de/en/scripts/wz_jsgraphics.js'> </script>

function drawLine(element1, element2) {
    var jg = new jsGraphics("renderGraph");
    var ele1 = document.getElementById(element1);
    var ele2 = document.getElementById(element2);
    jg.setColor("#DDD");
    jg.setStroke(5);
    jg.drawLine(ele1.offsetLeft + ele1.offsetWidth/2 , ele1.offsetTop + ele1.offsetHeight/2, ele2.offsetLeft + ele2.offsetWidth/2, ele2.offsetTop + ele2.offsetHeight/2);
    jg.paint();
}