How to arrange several hundred nodes in symmetrical concentric circles based on selection criteria in D3 forced layout?

亡梦爱人 提交于 2019-12-24 04:18:12

问题


I'm pretty new to D3 and working with a force direction layout which currently has about a 1000 nodes. The visualization as of now looks as shown below:

In the above network, the red node in the center of the page is the root node, solid yellow nodes are level 1 nodes and yellow nodes with pie-slices in them are level 2 nodes. I have a property attached to each node, 'category' where

category = 1: root node
category = 2: level 1 node
category = 3: level 2 node

I'm unable to manipulate the charge/link-distance/friction in a way that the root node is in the center, level 1 nodes are neatly arranged around the root node and level 2 nodes are arranged in the outermost circle. This is the code snippet that I'm currently working with that creates and adjusts the force:

var zoom = d3.behavior.zoom()
        .scaleExtent([-1, 10])
        .on("zoom", zoomed);

    var drag = d3.behavior.drag()
        .origin(function(d) { return d; })
        .on("dragstart", dragstarted)
        .on("drag", dragged)
        .on("dragend", dragended);

    var force = d3.layout.force()       // charge is for inter-node repel, link distance is node-node distance
        .charge(function(d){ //originally charge was just -150 and there was no function
        var charge = -150;
        if (d.index === 0) 
            charge = 20 * charge;
        return charge;})
        .gravity(-0.01)     
        .linkDistance(function(d){ //originally charge was just 150 and there was no function
        var linkDist = 150;
        if (d.category == 2) 
            linkDist = 2 * linkDist;
        else if(d.category == 3)
            linkDist = 4 * linkDist;
        return linkDist;})
        //.linkStrength(0.2)
        .friction(0.9)
        .nodes(nodes)
        .links(links)
        .size([w, h])
        .start();

I hope this is enough for me to convey the problem. In the current code, I tried playing with charge and link-distance but it isn't working. I can further code if needed. Please can someone help me achieve the desired layout using the right d3 and force-layout properties? Thanks.

Edit: I'm currently using a tick function that looks like the following (not sure if this must be tweaked to manually position the nodes):

force.on("tick", function() {
        nodes[0].x = w / 2;
        nodes[0].y = h / 2;

        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 + ")"; });
    });

来源:https://stackoverflow.com/questions/30056786/how-to-arrange-several-hundred-nodes-in-symmetrical-concentric-circles-based-on

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