views:

5475

answers:

2

I have n <div>s, each with <h1> title and <ul> list of items in.

I would like to float these over a canvas and draw lines from <div id="x"> list item y to <div id="z">. I am using jQuery UI to make the <div>s draggable.

The canvas element is part way down the page (a paragraph of text and some form elements precede it) but I can change this if necessary.

[edit]

I tagged the question with graph, but let me add this link: Graph_(mathematics) :-)

+4  A: 

I would make the div's positioning to absolute and then set them where you want. Then get their position with this function:

//Get the absolute position of a DOM object on a page
function findPos(obj) {
    var curLeft = curTop = 0;
    if (obj.offsetParent) {
     do {
      curLeft += obj.offsetLeft;
      curTop += obj.offsetTop;
     } while (obj = obj.offsetParent);
    }
    return {x:curLeft, y:curTop};
}

When you have their position, add it to half their width/height, and you will have the position of their center on the page. Now find the position of the canvas and substract it from the previously found numbers. If you draw a line between those two points, it should link the two divs. In case it's not clear, here's how I would code it:

var centerX = findPos(document.getElementById('x'));
centerX.x += document.getElementById('x').style.width;
centerX.y += document.getElementById('x').style.height;
var centerZ = findPos(document.getElementById('Z'));
centerZ.x += document.getElementById('z').style.width;
centerZ.y += document.getElementById('z').style.height;
//Now you've got both centers in reference to the page
var canvasPos = findPos(document.getElementById('canvas'));
centerX.x -= canvasPos.x;
centerX.y -= canvasPos.y;
centerZ.x -= canvasPos.x;
centerZ.y -= canvasPos.y;
//Now both points are in reference to the canvas
var ctx = document.getElementById('canvas').getContext('2d');
ctx.beginPath();
ctx.moveTo(centerX.x, centerX.y);
ctx.lineTo(centerZ.x, centerZ.y);
ctx.stroke();
//Now you should have a line between both divs. You should call this code each time the position changes

EDIT By the way, using the findPos function you can also set the initial position of the divs relatively to the canvas (here at (30; 40)):

var position = {x: 30, y: 40};
var canvasPos = findPos(document.getElementById('canvas'));
var xPos = canvasPos.x + position.x;
var yPos = canvasPos.y + position.y;
document.getElementById('x').style.left = xPos+"px";
document.getElementById('x').style.top = yPos+"px";
dutchflyboy
+8  A: 

You should be able to use $().offset() to get the absolute page offset for each of the divs, and the canvas element. After that it's relatively trivial to use the canvas DOM functions to draw lines.

Here's a link to my implementation. http://servut.us/akx/stackoverflow/jquery-canvas-lines.html

AKX
Will this link be available forever? This was a really nice implementation, I added jQuery UI draggable and everything still worked fine :)
It'll be available for the foreseeable future, I should think. Glad you liked it!
AKX
BTW using the rel attribute to join items was a very neat idea :)