我希望从边界到边界的树节点距离相等,默认情况下是从中心到中心。
draw_tree()
function tree(root) {
var width = 300
var height = 140
var step = 50
var margin = {top: 0, right: 40, bottom: 0, left: 40}
var treemap = d3.tree().size([height,200])
var node = treemap(d3.hierarchy(root))
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var nodes = treemap(d3.hierarchy(root))
var g = svg.selectAll("g")
.data([nodes])
.enter().append("g")
.attr("class", "nodes")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var link = g.append("g")
.attr("class", "link")
.selectAll("path")
.data(function(d) { return treemap(d).links(); })
.enter().append("path")
.attr("class", "links")
.attr('fill','none')
.attr('stroke','black')
var node = g.append("g")
.attr("class", "node")
.selectAll("g")
.data(function(d) { return nodes; })
.enter().append("g")
.attr("class", "nodes")
node.append("rect")
.attr('fill','none')
var pos = []
var txt = node.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.attr("font-family", "sans-serif")
.attr('font-size',12)
.text(function(d) {
return d.data.type == 'hidden'?'':d.data.name;
})
.each(function(d,i,n) {
d.width = Math.max(50, this.getComputedTextLength() + 10);
d.height=20
if (d.data.type == 'hidden') {
d.width = 0
d.height = 0
}
})
.attr("x",0);
node.filter(function(d) { return "join" in d.data; }).insert("path", "text")
.attr("class", "join");
tick(svg);
return svg;
}
function tick(svg) {
var node = svg.selectAll(".node g")
.attr("class", function(d) { return d.data.type; })
.attr("transform", function(d, i) { return "translate("+ d.y + "," + d.x + ")"; })
node.select("rect")
.attr('stroke','black')
.attr("ry", 0)
.attr("rx", 0)
.attr('x',d => -d.width/2)
.attr("y", d => -d.height/2)
.attr("height", 20)
.attr("width", function(d) { return d.width; })
var diagjoin = function link(d) {
var sy = d.width
var sx = 0
var ty = 88
var tx = d.data.join * 24
return "M" + sy + "," + sx
+ "C" + (sy + ty) / 2 + "," + sx
+ " " + (sy + ty) / 2 + "," + tx
+ " " + ty + "," + tx;
};
var diagpath = function link(d) {
var sy = d.source.y
var sx = d.source.x
var ty = d.target.y
var tx = d.target.x
return "M" + sy + "," + sx
+ "C" + (sy + ty) / 2 + "," + sx
+ " " + (sy + ty) / 2 + "," + tx
+ " " + ty + "," + tx;
};
const zagzag1 = (d) => {
let from = d.source
let to = d.target
let dx = to.y - from.y;
let dy = to.x - from.x;
if (Math.abs(dx) > Math.abs(dy)) {
let mx,my,nx,ny,sx,sy
sx = (dx>0)?1:-1
sy = (dy>0)?1:-1
mx = from.y + from.width/2*sx
my = from.x
nx = to.y - to.width/2*sx
ny = to.x
dx = nx - mx;
dy = ny - my;
return `M ${mx},${my} l ${dx/2},0 0,${dy} ${dx/2},0 `;
}else{//vertical
let mx,my,nx,ny,sx,sy
sx = (dx>0)?1:-1
sy = (dy>0)?1:-1
mx = from.y
my = from.x + from.height/2*sy
nx = to.y
ny = to.x - to.height/2*sy
dx = nx - mx;
dy = ny - my;
return `M ${mx},${my} l 0,${dy/2} ${dx},0 0,${dy/2}`;
}
};
const zagzag = (d) => {
let from = d.source
let to = d.target
let dx = to.y - from.y;
let dy = to.x - from.x;
if (Math.abs(dx) > Math.abs(dy)) {
let mx,my,nx,ny,sx,sy
sx = (dx>0)?1:-1
sy = (dy>0)?1:-1
mx = from.y + from.width/2*sx
my = from.x
nx = to.y - to.width/2*sx
ny = to.x
dx = nx - mx;
dy = ny - my;
return `M ${mx},${my} l 0,${dy} ${dx},0`;
}else{//vertical
let mx,my,nx,ny,sx,sy
sx = (dx>0)?1:-1
sy = (dy>0)?1:-1
mx = from.y
my = from.x + from.height/2*sy
nx = to.y
ny = to.x - to.height/2*sy
dx = nx - mx;
dy = ny - my;
return `M ${mx},${my} l ${dx},0 0,${dy}`;
}
};
node.select(".join")
.attr("d",d => zagzag(d) );
svg.selectAll(".link path")
.attr("d", d => zagzag(d));
}
function draw_tree() {
tree(
{name:'AAAA',children:[
{name: "AAAA",type:'hidden', children: [
{name: "BBBB", children: [{name: "HHHH"}]},
{name: "CCCC", children: [{name: "IIII"}]},
{name: "DDDD", children: [{name: "JJJJ"}]},
{name: "EEEE", children: [{name: "KKKK"}]},
{name: "FFFF", children: [{name: "LLLL"}]},
{name: "GGGG", children: [{name: "MMMM"}]},
]}
]}
);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>