Yes, this could be fixed. The force.resume method is only called when
the mouse moves, so clicking itself would not trigger a resume.
However, the mouseup handler currently invokes the mousemove handler,
in dependent of whether or not the node was dragged; thus, if you
click without dragging, you'll receive the "click" event but the
layout will also restart. I think we could change this quite easily by
detecting if the mouse had moved before calling dragmove here:
https://github.com/mbostock/d3/blob/master/src/layout/force.js#L263
The simplest fix would be to move dragmove() into the if block, but
I'm not 100% it's the right fix:
if (d3_layout_forceDragMoved) {
d3_layout_forceStopClick = true;
d3_layout_forceCancel();
dragmove();
}
Another possibility is to remove dragmove() entirely, and just hope
that the browser reports every mousemove.
Mike
I just tested it locally and it worked fine for me, commenting out the
call to dragmove in the dragup handler. Can you post an example of
yours not working? Did you recompile d3.layout.js after making the
change to force.js? What browser are you using? What does the rest of
your code looked like.
Mike
I was referring to src/layout/force.js, not the force.js in the
examples directory. The file d3.layout.js is compiled from source
files in the src directory; by compiled, I simply mean that many small
files are concatenated into a larger file. Then d3.layout.min.js is
generated by minifying the large file using UglifyJS. This is all
specified in the Makefile. The point being, if you edit d3.layout.js,
you are editing an auto-generated file, and it's generally better to
edit the source file and run make.
> console.log("calling dragmove from dragup if block");
> dragmove(); //MH
Don't call dragmove here. Remove all calls to dragmove inside the
dragup handler.
Mike
No. It's true that whenever a mousemove occurs, the node is centered
on the mouse cursor. The layout does not preserve a fixed offset
between the node and the mouse, because we generally assume that the
nodes are small so this difference will be imperceptible. But, a
mousemove is only generated when the mouse moves, independent of where
you click relative to the node. So, it seems more likely that you are
moving the mouse when you are clicking… is that possible? Try clicking
more gently? :)
Mike
True, but in many cases it's not damaging to restart the layout, and
I'm wary of making the drag behavior either sluggish or imprecise.
Even small things like 500ms or 3px can be noticeable.
Another option might be for you to call force.stop() to stop the
layout immediately, either on mouseup or on click. And, if you want to
permanently stop the layout, you could also reassign the resume method
after the graph cools:
force.resume = function() { return force; }; // noop
Yet another option might be to be more conservative in the value of
alpha when resuming, so that the change is not as jarring. The graph
could heat up gradually rather than jumping immediately to alpha = .1.
Mike
There are times when the mouse can move between the last mousemove
event and the mouseup event, and I wanted the nodes to end up at the
mouse location. The fix (moving dragmove to the if dragmoved block)
has been merged and released:
https://github.com/mbostock/d3/commit/2440287d4558585a6d4673a2317cb376078d401a#src/layout/force.js
Mike