问题
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