在闪电中,我们正在使用D3js库在圆形树中显示径向树。当我们有大约15 个节点时,它看起来不错。
当我们尝试显示超过 15 条记录时,节点相互碰撞。
我需要在圆圈周围显示 40 多个节点,节点之间有良好的空间。
在这里,我分享了我的代码和屏幕截图
drawTree : function(component, event, helper, treeData) {
var textMaxLength = 0, radius = 50, circleTextLen = 0;
// Properly formatted treeData, if it's flat data, use stratify
console.log('treeData', treeData);
var margin = { top: 10, right: 10, bottom: 10, left: 10 },
width = 1200,
height = 1000;
// Prepare container
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height),
g = svg.append("g")
.attr("transform",
"translate(" + 450 + "," + 400 + ") scale(1) ");
var i = 0,
// duration = 750,
cluster_size = 800,
root;
// Define cluster
var cluster = d3.cluster()
.size([cluster_size, cluster_size]);
// Get the root
root = d3.hierarchy(treeData, function(d) {
return d.children;
});
// Collapse all children
if(typeof collapse === 'undefined') {
root.children.forEach(collapse);
}
root.x0 = 0;
root.y0 = 0;
// Start drawing
draw(root);
function draw(source) {
var treeData = cluster(root);
var nodes = treeData.descendants(),
links = treeData.descendants()
.slice(1);
var node = g.selectAll('g.node')
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});
// Enter the node, draw it at source, so that we can animate later from
// source
var nodeEnter = node
.enter()
.append('g')
.attr('class', 'node')
.attr("transform", function(d) {
return "translate(" + project(source, source.x0, source.y0) + ")";
})
.on('click', d => {
// d3.event.preventDefault();
if(d.data.level == 'subnode') {
component.set("v.nodeName", d.data.name);
}
})
.on("dblclick", click);
// Draw a circle with zero radius
nodeEnter.append('circle')
.attr('class', 'node')
.attr('r', 20)
.attr('stroke', 'steelblue')
.attr('fill', 'white')
.attr('stroke-width', '1.5px')
.attr('display', function(d) {
if(d.data.level == 'subnode' || d.data.level != 'node') {
return 'block';
} else {
return 'none';
}
});
//Draw text
nodeEnter.append("text")
// .attr("class","wrap")
.attr("dy", function(d) {
if(d.data.level == 'node') {
return '0.5em';
} else {
return '0.5em';
}
})
.style("text-anchor", 'middle')
.text(function(d) {
if(textMaxLength < (d.data.name).length) {
textMaxLength = (d.data.name).length;
}
return d.data.name;
})
// .style("font-size", "1px")
.call(wrap, 100)
.each(getSize)
.style('fill', function(d) {
return "white";
})
.style("font-size", function(d) {
return (d.scale + 10 + "px");
});
var nodeUpdate = nodeEnter.merge(node);
// When we enter the update phase, change the coordinate of each node using a
// transition, so that we can animate
nodeUpdate.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + project(d, d.x, d.y) + ")";
});
// Add color to circle
// Handle exit node, show a transition
var nodeExit = node.exit()
.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + project(source, source.x, source.y) + ")";
})
.remove();
// On exit reduce the node circles size to 0
nodeExit.select('circle')
.attr('r', 1e-6);
// On exit reduce the opacity of text labels
nodeExit.select('text')
.style('fill-opacity', 1e-6);
var link = g.selectAll('path.link')
.data(links, function(d) {
return d.id || (d.id = i);
});
// We need animation for links also, so we first draw paths whose start and origin is
// same
var linkEnter = link.enter()
.insert('path', "g")
.attr("class", "link")
.attr("stroke", "rgb(65, 136, 229)")
.attr("stroke-width", "1px")
.attr("d", function(d) {
return "M" + project(source, source.x0, source.y0)
+ "L" + project(source, source.x0, source.y0);
});
var linkUpdate = linkEnter.merge(link);
// Now animate the links
linkUpdate.transition()
.duration(duration)
.attr("d", function(d) {
return "M" + project(d, d.x, d.y)
+ "L" + project(d.parent, d.parent.x, d.parent.y);
});
// Remove any exiting links
var linkExit = link.exit()
.transition()
.duration(duration)
.attr("d", function(d) {
return "M" + project(source, source.x, source.y)
+ "L" + project(source, source.x, source.y);
})
.remove();
// Store the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function project(d, x, y) {
// Calculate angle, and adjust radius so that links are not too long.
// Start playing with radius and cluster_size.
var angle = (x - (cluster_size / 4)) / (cluster_size / 2) * Math.PI, radius = y * 0.5;
var cors = [radius * Math.cos(angle), radius * Math.sin(angle)];
return cors;
}
function collapse(d) {
if(d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
// We use this function, so that all nodes won't be drawn at same time.
// Play around with this and check it changes the output
// If you increase the "value", animation will be slower
function duration(d) {
var value = 300 + (d.id * 5);
// var value = 500+(d.id*5);
// var value = 1500+(d.id*5);
return value;
}
}