Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Draw arrow between lists

Is there any way to dynamically draw an arrow between the two highlighted list items?

So if I hovered over "Item 2" it would do this (but a straight arrow):

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

This is the code from the answer I got here a few mins ago:

Highlight item in two lists when mouseover

$(".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>
like image 993
bmaster Avatar asked Jan 12 '11 02:01

bmaster


3 Answers

You don't have to use 2D drawing here. Check this out: http://jsfiddle.net/vjYuW/ I just forked and updated the fiddle you have posted above.

Here is the essential code, it handles 3 DIVs 1 pixel wide or tall to draw the lines:

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");
});

Note: you will probably have to tweak it a little to support all browsers - I didn't check IE6 & Co.

like image 136
Alex Pakka Avatar answered Nov 17 '22 00:11

Alex Pakka


You can use the HTML5 canvas element to achieve this.

I'm not sure if this is the best way to do it, but I fiddled around and got this.

What I did is first I enclosed the lists in a div. The div is styled with CSS to have a relative position. This is so when you get the position with jQuery, it will give a position relative to that. Next, I put a canvas in front of the lists and disabled pointer events on it. I also added something to adjust the height of the canvas to the height of the lists. Then I added another handler for hover. When you hover over it, it will draw the arrow, and when you hover out, it'll clear the canvas.

To draw the arrow is fairly simple. First it gets the positions of the items. Then it draws a line and uses some math to orient the arrow. To get the positions is fairly easy. For the right list, you can just use the position method. For the left list, I created a temporary span and appended it to the list item, and then got the position of that.

like image 24
icktoofay Avatar answered Nov 16 '22 23:11

icktoofay


I think for something like this you may want to use a third party drawing library such as Vector Draw Library.

You can download the library from the link and add it to your app. Then:

Include it on your page:

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

Then add to your hover function:

$(".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();

Note that you will have to write the code to remove the line in the hover function otherwise once it is drawn it will remain. Also, I am using offset() to calculate the position of the items in the list. This should work but you may have to tweak a bit to get it to look right.

The above code works but is not complete. Maybe the second function in the hover can call clear() on the canvas. Canvas here is the enclosing div that encloses the two lists.

like image 3
Vincent Ramdhanie Avatar answered Nov 16 '22 23:11

Vincent Ramdhanie