Reputation: 9
I am relatively new to d3, and I'm still bumping into things that stump me.
Basically, I have a tree with draggable nodes. I want to restrict the "drag handle" of the nodes to only the circle, not the circle and text (and whatever else I end up adding).
I know that it has something to do with properly setting the origin in my drag behavior, but I just can't quite seem to get it.
I've found some useful information here on stackoverflow (sorry, I can only post two links), and looking at https://groups.google.com/forum/#!topic/d3-js/fjp1mpvVW1M it appears that I'm applying the drag behavior to a child element of a g container and then trying to apply the transform to its g container.
How can I accomplish this?
here's the relevant code:
var dragListener = d3.behavior.drag()
.origin(function () {
var t = d3.select(this);
return {
x: t.attr("x") + d3.transform(t.attr("transform")).translate[0],
y: t.attr("y") + d3.transform(t.attr("transform")).translate[1]
};
})
.on("drag", function (d) {
d.x0 += d3.event.dy;
d.y0 += d3.event.dx;
//var node = d3.select(this); //this works
var node = d3.select(this.parentNode) //this doesn't work
node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")");
});
var nodeEnter = node.enter().append("g")
//.call(dragListener) // this works
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click);
nodeEnter.append("circle")
.call(dragListener) // this doesn't work
.attr("r", 1e-6)
.style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
Here's a fiddle: http://jsfiddle.net/tsmith77/4R3Cb/
UPDATE
I wasn't able to get the child group to do what I wanted, but I accomplished what I want by intercepting the mousedown event on the text:
nodeEnter.append("text")
.on("mousedown", function (d) {
d3.event.stopPropagation();
})
.on("click", function (d) {
alert("text clicked");
})
This prevents the text from being a drag handle, but still allows me to perform an action when the text is clicked.
Upvotes: 0
Views: 997
Reputation: 10536
Set up following line in your CSS for text correspondent to nodes:
pointer-events: none;
(one way to do it would be to assign a class named let's say "node-label
" to all such texts, and then, to define that class' property "pointer-events
" as above)
This will prevent dragging by grabbing text.
I'll give you also two live examples. They deal with force layout, not tree like in your case, but it shouldn't matter, the principle is the same.
example 1 - dragging possible by grabbing both circles and labels
example 2 - dragging possible by grabbing only circles
The difference between them is only the line:
pointer-events: none;
Upvotes: 1