d3.js Force layout only applied vertically

泄露秘密 提交于 2019-12-24 00:03:08

问题


I'm doing a data visualisation with d3. To give you some context,

  • the graph contains about 400 nodes (all data is loaded from multiple json files) that are connected to each other
  • they are all mapped by year in a timeline (x axis)
  • the position in the y axis is completely randomized
  • the nodes have all different sizes

Now my question:
How can I distribute the nodes in the y axis so that they don't overlap?

You can checkout the full sourcecode on the GitHub Repository (work in progress - currently on the real-database branch).

This is a screenshot of how it currently looks:


回答1:


Basically, in the tick() function, reset the nodes array x values to what you want them to be (presumably some scale to do with year), and the node and links will be drawn at those x values, and subsequent force calculations will start again from those values too

force.on("tick", function() {

    // Adjust to what you want nodePos to be, here I'm just doing it by index
    graph.nodes.forEach (function(nodePos,i) {
        nodePos.x = i * 15;
        //nodePos.x = xscale (data[i].year); // or whatever
     })

   // then normal node/link layout

I've forked this standard force-directed example by blt909 to show one way it could be done --> http://jsfiddle.net/vztydams/

PS If you have a lot of items and very few discrete x values, best to give them a bit of wiggle room at first (i.e. a range in x they're contained to rather than a value), then slowly narrow that range down. Otherwise nodes will get 'stuck' behind each other.

Edit 02/03/16:

Hi Alvaro, essentially the graph.nodes is your linked data, as these are the objects that are attached to the displayed nodes as the data.

So if I set up a scale, and stick in a random year per datum:

var dom = [1994,2014];
var xscale = d3.scale.linear().domain(dom).range([20,400]);
graph.nodes.forEach (function(datum) {
    datum.year = dom[0] + Math.floor (Math.random() * (dom[1] - dom[0]));
});

...

We can then restrict the x position of each node's datum like this:

graph.nodes.forEach (function(d,i) {
    //d.x = i * 15;
    d.x = xscale(d.year);
})

(As I say, if you have a lot of nodes and few years, you'd be better restricting to a range and then narrowing that range down on each subsequent tick)

http://jsfiddle.net/vztydams/2/



来源:https://stackoverflow.com/questions/35585192/d3-js-force-layout-only-applied-vertically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!