D3.js packed circle layout - how to adjust child radius

╄→гoц情女王★ 提交于 2019-12-01 09:26:21

问题


I am currently useing d3's packed cicle layout(this) and have noticed that when a parent only has one child, the radius of the child is the same as the parents.

Is it possible to modify this using the the .radius method the layout provides? Ideally if a parent only has one child the child's radius should be 1/2 of the parents.

i found a partial solution, which is to add placeholder nodes to the tree, then run the layout, then remove them again. But this isnt exactly what i want, since it makes the layout look on sided.

Hope this makes sense. take a look at the fiddle to see what i mean: jsfiddle

The below posted sample should show two circles( like in circle 2 in the img).

var root = {
     "name": "controls",
     "children": [
      {"name": "AnchorControl", "size": 2138}
     ]
};

thx


回答1:


I took a stab at it and managed to solve the issue. Might not be optimal but hey, it works. =)

this.calculateLayout = function( dim, tree ) {

    var packlayout = d3.layout.pack()
        .size( [dim, dim] )
        .padding( 80 )
        .sort( d3.descending )
        .value( function( d ) { return 150 } );

    addPlaceholders(tree);

    var nodes = packlayout( tree );

    removePlaceholders(nodes);

    centerNodes( nodes );

    makePositionsRelativeToZero( nodes );

    return nodes;
};

function addPlaceholders( node ) {

    if(node.children) {

        for( var i = 0; i < node.children.length; i++ ) {

            var child = node.children[i];
            addPlaceholders( child );
        }

        if(node.children.length === 1) {

            node.children.push({ name:'placeholder', children: [ { name:'placeholder', children:[] }] });
        }
    }
};

function removePlaceholders( nodes ) {

    for( var i = nodes.length - 1; i >= 0; i-- ) {

        var node = nodes[i];

        if( node.name === 'placeholder' ) {

            nodes.splice(i,1);
        } else {

            if( node.children ) {

                removePlaceholders( node.children );
            }
        }
    }
};

function centerNodes( nodes ) {

    for( var i = 0; i < nodes.length; i ++ ) {

        var node = nodes[i];

        if( node.children ) {

            if( node.children.length === 1) {

                var offset = node.x - node.children[0].x;
                node.children[0].x += offset;
                reposition(node.children[0],offset);
            }
        }
    }

    function reposition( node, offset ) {

        if(node.children) {
            for( var i = 0; i < node.children.length; i++ ) {

                node.children[i].x += offset;
                reposition( node.children[i], offset );
            }
        }
    };
};

function makePositionsRelativeToZero( nodes ) {

    //use this to have vis centered at 0,0,0 (easier for positioning)
    var offsetX = nodes[0].x;
    var offsetY = nodes[0].y;

    for( var i = 0; i < nodes.length; i ++ ) {

        var node = nodes[i];

        node.x -= offsetX;
        node.y -= offsetY;
    }
};



回答2:


I haven't looked at v3 of D3, but v4 has pack.padding() method that you can specify the amount of padding to include.

See the example image, the circle on the right is a solo child.



来源:https://stackoverflow.com/questions/22307486/d3-js-packed-circle-layout-how-to-adjust-child-radius

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