Positioning graph within div

2,252 views
Skip to first unread message

stephenhay

unread,
Apr 30, 2011, 4:25:53 PM4/30/11
to d3-js
When loading a page with a force-directed graph, the graph seems to
place itself (randomly?) within the parent div. Sometimes, part of the
graph is rendered outside the div (in the overflow), which makes it
invisible, even though the graph is small enough to fit within the
allotted space.

Is there any way to set a fixed position where the graph is rendered?

Mike Bostock

unread,
Apr 30, 2011, 5:54:08 PM4/30/11
to d3...@googlegroups.com
The force layout's position is determined by the size you specify
(width and height). The size affects the initial random positioning of
nodes, and the location of the center gravity.

If your graph is too big to fit, then you can try increasing the
gravity strength, decreasing the charge strength, and decreasing the
link distance. If your graph isn't too big, but is centering around
the wrong location, then try adjusting the size property. You can also
reposition the graph by putting it inside an svg:g element and
applying a transform (translate). If you don't want random initial
positioning, you can initialize the `x` and `y` attributes of each
node before you start the force layout; however, the graph will still
gravitate towards the layout's center as set by the size property.

For example, this graph is 960x500, centered at 480x250:

http://mbostock.github.com/d3/ex/force.html

Mike

stephenhay

unread,
May 1, 2011, 3:40:03 AM5/1/11
to d3-js
Thanks, Mike.

I played around with the things you mentioned. An example of the
problem:

http://graph.zerointerface.nl/example.html

Here, if you reload the page, on every reload it seems that the
gravity center shifts and is seldom actually in the center, even
though the size specified remains the same. Tweaking the factors you
mentioned doesn't seem to help.

I must be doing something wrong to cause this. Could it be my use of
images and text?

Steve

Mike Bostock

unread,
May 1, 2011, 1:08:34 PM5/1/11
to d3...@googlegroups.com
Hi Steve,

I have a few recommendations.

1. Upgrade to the latest version of D3. There have been a lot of
improvements to the force-directed layout recently. In particular, I
just fixed a bug regarding node positioning using the transform
attribute, which is relevant to your example. The latest is 1.14.1:

https://github.com/mbostock/d3/zipball/v1.14.1

Once you upgrade, you'll need to include d3.geom.js (or
d3.geom.min.js) as another script, because the force layout now uses a
quadtree to approximate the repulsive charge forces.

2. Use an svg:g element to group your node image and text elements,
rather than svg:svg. The g element is the standard way to group things
in SVG, and it's a lot more efficient than embedding another SVG
container:

http://www.w3.org/TR/SVG/struct.html#Groups

Rather than setting the "x" and "y" attribute on the node (g) element,
you'll now be setting the "transform" attribute to translate the g
container into position:

http://www.w3.org/TR/SVG/coords.html#TransformAttribute

This is where the bug fix in 1.14.1 comes into play. Previously, the
force layout would compute the mouse position relative to the node
itself, so if the node was transformed, the mouse position was
incorrect. I've fixed this bug so the layout computes the position
relative to the nodes' parent container, which allows you to use svg:g
elements to transform nodes.

3. Rather than offsetting the nodes by (-10,-10) to accommodate the
image, offset the image by (-10,-10). This positions the nodes more
precisely under the mouse.

I updated your browse.js here:

https://gist.github.com/950642

Mike

stephenhay

unread,
May 1, 2011, 5:03:59 PM5/1/11
to d3-js
Wow, Mike. That helps a lot. The graph is now almost consistently
centered. Thank you!

There is now a cosmetic issue where when the graph is forming, it does
this mostly out of view and a few flashes of nodes are visible before
the entire graph eases in from one the sides. Less spectacular than
the older version and somewhat quirky, but an opacity transition at
the beginning softens it up nicely.

Now I know what you meant when you told me to play around with the
gravity and the charge. :)

Thank you so much for your help!

Steve

Mike Bostock

unread,
May 1, 2011, 5:59:16 PM5/1/11
to d3...@googlegroups.com
> There is now a cosmetic issue where when the graph is forming, it does
> this mostly out of view and a few flashes of nodes are visible before
> the entire graph eases in from one the sides.

Yep. Mainly it's because there's very little structure in your
(example) graph, so I increased the repulsive charge force
dramatically to overcome the gravity.

If you use the default settings, there will be less volatility when
the graph initializes, but it also will be less likely to stabilize on
the root node being in the center. You could play around with changing
the parameters after a short delay, which will give the graph a chance
to stabilize before you increase the strength of the forces.

Also, you could fix the root node in the center by setting the `x` and
`y` attributes, and setting `fixed` to true.

Or, if you're visualizing a tree structure rather than an arbitrary
graph, you could use one of the tree layouts (tree, cluster,
partition).

Mike

stephenhay

unread,
May 2, 2011, 3:02:56 AM5/2/11
to d3-js
Again, thank you!

Steve
Reply all
Reply to author
Forward
0 new messages