force.drag and vis.zoom conflicting each other?

338 views
Skip to first unread message

davidh

unread,
Sep 10, 2011, 6:25:38 AM9/10/11
to d3-js
Hi,

I'm using a force directed graph. Everything is great.
I just need to be able to drag and zoom with mousewheel.

I've almost achieved it. I can drag and I can zoom (with a double
click, I would like to be able to do it with mousewheel though).
But, now I can't drag my nodes anymore. It seems the dragging of the
panel is overriding the drag of the nodes.

Here is part of my code:

var vis = d3.select("#fig")
.on('DOMMouseScroll', function()
{ d3.event.preventDefault() })
.append("svg:svg")
.call(d3.behavior.zoom().on('zoom', redraw))
.append("svg:g")
.attr("pointer-events", "all")
.attr("width", w)
.attr("height", h);

var node = vis.selectAll("g.node")
.data(myndtags.nodes)
.enter().append("svg:g")
.attr("pointer-events", "all")
.attr("class", "node")
.attr("r", r - .75)
.style("fill", function (d) { return fill(d.group); })
.call(force.drag);

force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) { return "translate(" + d.x
+ "," + d.y + ")"; });
});

// This function is called when I'm dragging. If I put a
"return" at the beginning I can drag my nodes again like before.
function redraw() {
vis.attr("transform",
"translate(" + d3.event.translate + ")"
+ "scale(" + d3.event.scale + ")");
}


What should I do to be able to drag/zoom the panel but still be able
to drag my nodes?
Is it possible to know that my mouse is on a node? (and in that case
return in my redraw() function)

Thanks for the help!

davidh

unread,
Sep 10, 2011, 8:02:12 AM9/10/11
to d3-js
I've almost done it. Not sure if it's the good way to do it though.

I'm now binding the 'mouseup' event on my vis object.
I'm basically doing:
function mouseup() {
dragging = false;
}

On my nodes I'm binding the 'mousedown' event. With this function:
function mousedown() {
dragging = true;
}
And in my redraw() function, I'm returning if (!dragging) is true.

But now I have a strange behavior.
I can drag my nodes. When I stop dragging, if I'm trying to pan with
my mouse, my cursor is jumping to the previous position of the dragged
node. Everything works after that. But it's a little disturbing for
the user.

Any ideas?

davidh

unread,
Sep 24, 2011, 9:58:40 AM9/24/11
to d3-js
Hi,


To fix the zoom problem which didn't work with the mousewheel I
patched the src/behavior/zoom.js in d3.
42,43c42,44
< if (!d3_behavior_zoomZooming) d3_behavior_zoomZooming =
d3_behavior_zoomLocation(d3.svg.mouse(d3_behavior_zoomTarget));
< d3_behavior_zoomTo(d3_behavior_zoomDelta() + xyz[2],
d3.svg.mouse(d3_behavior_zoomTarget), d3_behavior_zoomZooming);
---
> var mouse = d3.svg.mouse(d3_behavior_zoomTarget);
> d3_behavior_zoomZooming = d3_behavior_zoomLocation(mouse);
> d3_behavior_zoomTo(d3.event.wheelDelta < 0 ? Math.ceil(xyz[2] - 1)*0.7 : Math.floor(xyz[2] + 1)*0.7, mouse, d3_behavior_zoomZooming);

So basically I'm just checking if the wheelDelta of the d3.event is a
wheelup or a wheeldown and make the zoom accordingly like in the
dbclick() callback.

I still have my problem with panning after dragging nodes. It's buggy.
The mouse is coming back to the last "mousedown" position where I
dragged my node. After that everything is working great.

Thanks,
Reply all
Reply to author
Forward
0 new messages