First off, for simplicity's sake here is a fiddle on how to draw a basic Line with your mouse and KineticJS: http://jsfiddle.net/projeqht/fF3hh/
Let's say you already have two circles on the stage, and you need to draw a line to connect them.
We can use e.targetNode to select the nodes on each event (mousedown, mouseup), for example:
layer.on("mousedown", function (e) {
var nodeDown = e.targetNode;
}
layer.on("mouseup", function (e) {
var nodeUp = e.targetNode;
}
We need to check if the parent of nodeDown is a Kinetic.Group or something else.
- If the target node
nodeDown has a Kinetic.Group for a parent, we can use this Group to store the new line, and the 2nd target node nodeUp.
- If the target node
nodeUp does not have a Kinetic.Group for a parent, we need to see if nodeUp has a Group for a parent. If nodeUp has a Kinetic.Group for a parent, then we can use that Group to store the new line, and the first target node nodeDown.
- If neither
nodeDown or nodeUp have a group for a parent, then we will need to create a new group for them and add all 3 shapes (2 circles and a line) to that new group.
Use this tutorial to learn how to move shapes from 1 group to another: http://www.html5canvastutorials.com/kineticjs/html5-canvas-move-shape-to-another-container-with-kineticjs/
Also, if you move a shape from one group to another, you may want to remove() or destroy() the extra group if it is no longer needed.
While drawing a Line, you will have to disable dragging the shapes, so that you can drag and draw with a mouse. You can do that by doing something similar to this:
function stopDrag() {
for (var i=0; i<layer.children.length; i++) {
layer.children[i].setDraggable(false);
}
}
function startDrag() {
for (var i=0; i<layer.children.length; i++) {
layer.children[i].setDraggable(true);
}
}
This will make all the children of layer draggable and undraggable, but you might want to limit that by being more specific than select layer.children. A nice trick I liked to use here was to name all groups that were draggable as "draggable_shapes" and then use var draggableArray = stage.get('.draggable_shapes') to select all the groups that are allowed to be dragged, then you could loop through that array and setDraggable().
Another point to note is that the X and Y coordinates of the Line will be a bit tricky to calculate, depending on if it has a Group as a parent or a Layer. If the Line is grouped, line's coordinates will be relative to the Group position, or else the Line's coordinates will be relative to the Stage (top left corner).
This will get you started on connecting a line with two different circles. It's up to you to do the coordinate logic if you want the lines to only connect on the outer rim of the circles.
Maybe you might want to add a transparent rectangle (attribute opacity: 0) behind each circle, so that on mousedown with the rectangle, you will call drawLine() to start drawing a line. Or else if the user clicks the circle, it will drag the group. At least that has similar functionality to the lucid charts application.
Custom Hit Function (http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-custom-hit-function-tutorial/) would probably be a cleaner way to do this but I'm not 100% on using Custom Hit Functions, someone else might know better.
Let me know if you need further help. Good luck!