2.8.1 version: problems with drag/translate/zoom and force layout

1,546 views
Skip to first unread message

CG

unread,
Mar 2, 2012, 2:08:15 PM3/2/12
to d3-js
Hi all
Thanks a lot for the new version.
Just want to mention that some stuff that used to work nicely with the
previous version seems to fail (no error message, but not working
properly anymore). More specifically, in the main force layout
example, this little zoom addition below is not working anymore (I
guess the d3.event should stop propagate somewhere...) .

Again, thanks for this brilliant piece of code ; )
C.

var width = 960,
height = 500;

var color = d3.scale.category20();

var force = d3.layout.force()
.charge(-120)
.linkDistance(30)
.size([width, height]);

// ADD
// ******
var drawZoom = function() {svg.attr("transform","translate(" +
d3.event.translate + ")"+ " scale(" + d3.event.scale + ")");};

var svg = d3.select("#chart").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().on("zoom", drawZoom))
.call(function(){this.insert('svg:rect')
.attr('width', '100%')
.attr('height', '100%')
.attr('fill', 'grey')})
.append('svg:g')

// END ADD
// ************

d3.json("miserables.json", function(json) {
force
.nodes(json.nodes)
.links(json.links)
.start();

var link = svg.selectAll("line.link")
.data(json.links)
.enter().append("line")
.attr("class", "link")
.style("stroke-width", function(d) { return
Math.sqrt(d.value); });

var node = svg.selectAll("circle.node")
.data(json.nodes)
.enter().append("circle")
.attr("class", "node")
.attr("r", 5)
.style("fill", function(d) { return color(d.group); })
.call(force.drag);

node.append("title")
.text(function(d) { return d.name; });

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("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
});



Jason Davies

unread,
Mar 2, 2012, 3:48:51 PM3/2/12
to d3...@googlegroups.com
On Fri, Mar 02, 2012 at 11:08:15AM -0800, CG wrote:
> Just want to mention that some stuff that used to work nicely with the
> previous version seems to fail (no error message, but not working
> properly anymore). More specifically, in the main force layout
> example, this little zoom addition below is not working anymore (I
> guess the d3.event should stop propagate somewhere...) .

Try this instead:

svg.append("rect")


.attr("width", "100%")
.attr("height", "100%")
.attr("fill", "grey")

.call(d3.behavior.zoom()
.on("zoom", function() {


svg.attr("transform", "translate(" + d3.event.translate +

")scale(" + d3.event.scale + ")");
}));

svg = svg.append("g");

The problem with your version is that your zoom behaviour was bound to the
<svg> element. This means that it will receive any "mousedown" events
propagated from child elements. The drag behaviour doesn't prevent mousedown
from being propagated (and I don't think it should, because you may want to
handle this event for some reason). So the solution is to only listen for
mousedown (via the zoom behaviour) on the area that you wish to make zoomable
i.e. the background rectangle in your case.

Bind the zoom behaviour to this rectangle and it works as expected.

--
Jason Davies, http://www.jasondavies.com/

CG

unread,
Mar 4, 2012, 11:06:12 AM3/4/12
to d3-js
; ) Thanks
C.

Oleksandr Melnyk

unread,
Mar 19, 2012, 5:39:26 PM3/19/12
to d3-js
"I
> guess the d3.event should stop propagate somewhere..." - you are completely right.
I found code in d3.v2.js:
function mousedown() {

var target = this,
event_ = event.of(target, arguments), ....

and added "d3.event.stopPropagation();" at the beginning of function
body.
And this solved that drag conflict

Rick Jolly

unread,
Jun 14, 2013, 4:05:56 PM6/14/13
to d3...@googlegroups.com
I wonder if I can get an update on this problem. Zoom/pan will not work reliably with D3.js after version 1. 

Working plunker using version 1: http://plnkr.co/edit/lbKB9JMWK0Od8YkgvVUq?p=preview
Same plunker using version 3  will not allow node dragging: http://plnkr.co/edit/5l9FQbnAfRoMA4ulBLPK?p=preview

Now I did experiment with adding the zoom to the rectangle as suggested by Jason Davies. That turns out to be buggy. The zoom/pan is janky and eventually the graph zips off screen for some reason. Please uncomment the zoom/pan on the rectangle in either plunker to verify this behavior. 

Thanks

Rick Jolly

unread,
Jun 14, 2013, 4:10:45 PM6/14/13
to d3...@googlegroups.com
Correction: Zoom/pan will not work reliably with drag with D3.js after version 1

Jason Davies

unread,
Jun 14, 2013, 5:16:28 PM6/14/13
to d3...@googlegroups.com
On Fri, Jun 14, 2013 at 01:05:56PM -0700, Rick Jolly wrote:
> Working plunker using version 1:
> http://plnkr.co/edit/lbKB9JMWK0Od8YkgvVUq?p=preview
> Same plunker using version 3 will not allow node dragging:
> http://plnkr.co/edit/5l9FQbnAfRoMA4ulBLPK?p=preview

We are looking into the possibility of stopping event propagation by
default in both drag and zoom behaviours. But for now either the
solution with a rect should work, or alternatively you can add your own
event listener to your nodes and call d3.event.stopPropagation():

// …
.enter().append("circle")
.attr("r", 6)
.call(force.drag)
.on("mousedown", function() { d3.event.stopPropagation(); });

> Now I did experiment with adding the zoom to the rectangle as suggested by
> Jason Davies. That turns out to be buggy. The zoom/pan is janky and
> eventually the graph zips off screen for some reason. Please uncomment the
> zoom/pan on the rectangle in either plunker to verify this behavior.

I don't think you copied my code exactly, although I must admit it could
have been clearer, because it reassigns the svg variable after appending
the <rect>. Slightly clearer might be to declare a new variable g, and
refer to that in the zoom handler:

var svg = …;

svg.append("rect") // this rect never moves
.call(d3.behavior.zoom()
.on("zoom", function() {
// …
g.attr("translate", …);
});

var g = svg.append("rect"); // this group moves

You hadn't copied the last line, which reassigned the svg variable to
point to the group element, which is why you experienced unexpected
results.
Reply all
Reply to author
Forward
0 new messages