3

I want to be able to click on a container/shape and as I move the mouse a line that can be connected to another container/shape (with an arrow at one end) is drawn. Ideally I want this line to snap to the destination element.

I'm new to EaselJS and I've got no clue on how to go about this. This is the closes I've come across of here, and I can't make sense out of it: Drawing a Line in a html5 canvas using EaselJS

Community
  • 1
  • 1
Mossi
  • 997
  • 5
  • 15
  • 28
  • You question is somewhat to vague for SO, what you would need is probably more a tutorial than a simple answer. But to cover the basic steps: When the mouse is pressed and moving, you would just delete the old line and redraw a line from a fixed start-point to the current's mouse local position, to make it snap you would have to calc the distance from the mouseX/Y to the targetX/Y and if the distance is below a certain threshold you use the targetX/Y instead of the mouseX/Y. – olsn Apr 03 '14 at 11:50

1 Answers1

6

Here is a quick demo I put together

The key steps are:

  • Listen for mousedown on the initial item
  • Create a shape to draw the connection when the mouse is pressed
  • Listen for mousemove and mouseup on the stage (Note: You can use pressmove on the target to make this work a little more cleanly, but you will not get additional rollovers)
  • On mousemove, redraw the connection. In this case, I placed the connection on top of the initial target, so I have to offset the end point to compensate. I did this to avoid tracking the initial target)
  • On mouse up, stop the mousemove/mouseup, and determine what the mouse was released on. In this case, I removed the connection if there was no target, and redrew the connection a different color (and snapped to the center) otherwise.

http://jsfiddle.net/lannymcnie/6rh7P/

// Listen for press
end.on("mousedown", handlePress);

// Listen for move/end
stage.addEventListener("stagemousemove", drawLine);
stage.addEventListener("stagemouseup", endDraw);

// Redraw (and remember to clear)
connection.graphics.clear()
   .s("#f00")
   .mt(0,0).lt(stage.mouseX-connection.x, stage.mouseY-connection.y);

// Get the drop target(s)
var targets = stage.getObjectsUnderPoint(stage.mouseX, stage.mouseY);

// Stop Listening
stage.removeEventListener("stagemousemove", drawLine);
stage.removeEventListener("stagemouseup", endDraw);
// Note: This will be a little harder if you are using object-oriented approach, because the scope gets lost.

I thought this was in interesting challenge to bang out in 15 minutes. Hope it helps! Cheers.

[UPDATE]

In EaselJS 0.8+, you can save any graphics command, and update its values any time. This prevents you from having to redraw your whole shape every frame. Quick example:

connection.graphics.s("#f00").mt(0,0);
var command = connection.graphics.lt(0,0).command;

// Then later
command.x = stage.mouseX-connection.x;
command.y = stage.mouseY-connection.y;
stage.update();

Here is a sample showing Graphics commands (unrelated to this example) http://jsfiddle.net/lannymcnie/L2tm9xdm/

Lanny
  • 11,244
  • 1
  • 22
  • 30
  • Note: You could definitely do distance-based checks -- but the `getObjectsUnderPoint` is pixel-perfect, so I thought it was a better approach for this sample. – Lanny Apr 03 '14 at 18:08
  • Beautiful answer. This taught me a whole lot about EaselJS; I had no idea that the line had to be cleared and redrawn on tick. I'll use this as the bedrocks of my script. Thanks again! – Mossi Apr 04 '14 at 06:19
  • Happy to help. Maybe I will polish this up, and make it an official sample for EaselJS. – Lanny Apr 04 '14 at 18:19
  • Any chances I could ask how I can "attach" the end of the line to the shape/container? I want the line to move as I drag the target container/shape around. Search/reading the manual hasn't helped at all. As an additional question, can I "draw" an arrow instead of a line with EaselJS? or do I need to use static images? Cheers! – Mossi Apr 05 '14 at 23:41
  • To attach the lines to the targets, and move the targets, you would have to track all the connections, and redraw the connections each time. To this end, once a target is made, it can just be added to a single shape, which manages redrawing connections between targets. – Lanny Apr 06 '14 at 17:06