The above topic kept me busy for an exhausting dozen of hours when I wan trying to implement a simple dragging functionality. Basically the components I had were two SVG groups, one called input and the other, output and some lines connecting them. The mapping functionality had been achieved earlier in
this post, and the new requirement was to make each container draggable.
The problem:
At first I tried to use d3.event.x and d3.event.y to update the x attribute of the component. As in:
var drag = d3.drag().on("drag", function() {
var x = d3.event.x;
var y = d3.event.y;
d3.select(this).attr("transform", "translate(" + x + "," + y + ")");
});
In the that approach, the lines were appended to whichever the container the drag was started from, therefore there was the possibility of lines belonging to both the containers. The observations were that the drag was not smooth and the target ends of the lines that were belonging to the dragged container were not updated (obviously!)
When I was looking into the details of making the drag smooth, I came up with multiple event handlers that could be used.
d3.event vs d3.mouse
d3.event and
d3.mouse are two important
events defined by d3. The main difference between these two is that d3.event is browser-dependent while d3.mouse is not.
mbostock in StackOverflow responded to
this question saying that:
Instead of using d3.event, which is the browser's native event, use d3.mouse to get the coordinates relative to some container.
d3.event.pageX and d3.event.pageY
pageX and
pageY belong to d3.event and therefore are native to browser’s implementation.
Further more,
Lars says in
this that:
pageX and pageY are the event's native properties, which are browser-dependent (as you've discovered). These properties depend on the implementation of the rendering engine. In theory, they're specified in a W3C standard, but in practice the implementations don't necessarily conform to that standard.
d3.event.dx and d3.event.dy
Ultimately, my solution for a smooth drag was using d3.event.dx and d3.event.dy which return the delta values of the mouse movement.
In the words of
Naga on
this post:
d3.event.dx returns the x delta that the mouse has moved w.r.t to the x-coordinate from where the drag event started.
The final solution:
Finally my container dragging functionality gave out smooth results as:
var drag = d3.drag().on("drag", function() {
this.x = this.x || 0;
this.y = this.y || 0;
this.x += d3.event.dx;
this.y += d3.event.dy;
d3.select(this).attr("transform", "translate(" + this.x + "," + this.y + ")");
});
The working full code relevant for this functionality can be found stuffed up in
my Github commit.