There is a tiny gotcha when using d3.behavior.drag, which is that you
need to store the drag origin if you want to restrict the dragged
element to a particular area. A simple example is in:
http://www.jasondavies.com/morley-triangle/
The relevant code is:
var circle = vis.selectAll("circle")
.data(ps);
circle.enter().append("svg:circle")
.attr("r", 7.5)
.call(d3.behavior.drag()
.on("dragstart", function(d) {
this.__origin__ = d.slice();
})
.on("drag", function(d) {
d[0] = Math.max(0, Math.min(this.__origin__[0] += d3.event.dx, w));
d[1] = Math.max(0, Math.min(this.__origin__[1] += d3.event.dy, h));
update();
})
.on("dragend", function() {
delete this.__origin__;
}));
circle
.attr("cx", function(d) { return d[0]; })
.attr("cy", function(d) { return d[1]; });
It would be nice if d3.behavior.drag did something like this automatically, but
I haven't come up with an elegant solution yet. Perhaps an optional "origin"
accessor?
If you don't care about restricting the position, you can drop the "dragstart"
and "dragend" listeners and just do:
d[0] += d3.event.dx;
d[1] += d3.event.dy;
--
Jason Davies, http://www.jasondavies.com/
vis.append("svg:rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 100)
.attr("height", 100)
.call(d3.behavior.drag()
.on("drag", function(d) { console.log("d3.event.dx=" + d3.event.dx); });
results in the following output when dragged left:
d3.event.dx=-1
d3.event.dx=-4
d3.event.dx=5
d3.event.dx=-7
d3.event.dx=6
d3.event.dx=-8
d3.event.dx=7
Is there anything wrong here that causes the d3.event.dx to keep switching signs?
Thanks!
Your code as given above works fine for me. Note that the mouse
position is computed relative to the dragged element's parent container,
so if you are moving the container when dragging, this could cause the
behaviour you're seeing. Perhaps you could post a working example if
you're still stuck?
Specifically, if you are applying a "transform" attribute to the same
element to which you applied the drag behavior, bad things will
happen. If you're setting x & y attributes, you should be okay, or if
you assign the drag behavior to an enclosing svg:g element instead.
Mike