我根据Bernhard Zuba's D3.js Organizational Chart在D3中创建组织结构图。组织结构图模拟了一个组织,其中任何给定的人(由白色方块表示)可能在其下方有一百个左右的人(一个非常扁平的树结构,黑色贝塞尔曲线代表每个父子关系)。
问题在于,子节点和父节点之间的链接往往全部聚集在一起,导致非常粗的黑色线条具有非常渐变的斜率,这可能会有点像眼睛。
我用来生成链接的功能如下:
// Diagonal function
var diagonal = d3.svg.diagonal()
.source(function (d) {
return {
x: d.source.x + (rectW / 2),
y: d.source.y + rectH - 10
};
})
.target(function (d) {
return {
x: d.target.x + (rectW / 2),
y: d.target.y + 10
};
})
.projection(function (d) {
return [d.x, d.y];
});
此处,rectW
是每个节点的宽度,rectH
是每个节点的高度。
我想做的是对用于生成链接的贝塞尔函数稍作调整。具体来说,我想稍微压平控制点,以使曲线起点和终点的曲线更具戏剧性。如果有人能告诉我如何改变diagonal()
生成贝塞尔曲线所使用的函数,我可以弄清楚其余部分。
答案 0 :(得分:1)
如果您查看svg.diagonal的源代码,我无法真正看到调整只是控制点的直接方法。您认为可以使用projection,但这将转换用于生成路径的所有4个点。现在,我想我们可以通过投影获得一点点hacky并做这样的事情:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.17" data-semver="3.5.17" src="https://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script>
var data = [{
source: {
x: 10,
y: 10
},
target: {
x: 200,
y: 200
}
}, {
source: {
x: 50,
y: 50
},
target: {
x: 200,
y: 200
}
}];
var svg = d3.select('body')
.append('svg')
.attr('width', 205)
.attr('height', 205);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
if (!this.times) this.times = 0;
this.times++;
console.log(this.times);
if (this.times === 1) {
return [d.x, d.y];
} else if (this.times === 2) {
return [d.x - 25, d.y]
} else if (this.times === 3) {
return [d.x + 25, d.y];
} else if (this.times === 4) {
this.times = 0;
return [d.x, d.y];
}
});
svg.selectAll('path')
.data(data)
.enter()
.append('path')
.attr('d', diagonal)
.style('fill', 'none')
.style('stroke', 'black');
</script>
</body>
</html>
我可能在想这个。你自己可能只是更好地绘制弧线:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.17" data-semver="3.5.17" src="https://d3js.org/d3.v3.min.js"></script>
</head>
<body>
<script>
var data = [{
source: {
x: 10,
y: 10
},
target: {
x: 200,
y: 200
}
}, {
source: {
x: 200,
y: 10
},
target: {
x: 10,
y: 200
}
}];
var svg = d3.select('body')
.append('svg')
.attr('width', 205)
.attr('height', 205);
svg.selectAll('path')
.data(data)
.enter()
.append('path')
.attr('d', function(d){
var s = d.source,
t = d.target,
m = (s.y + t.y) / 2,
p0 = [s.x, s.y],
p1 = [s.x, m],
p2 = [t.x, m],
p3 = [t.x, t.y];
// adjust constrol points
p1[0] -= 25;
p2[0] += 25;
return "M" + p0 + "C" + p1 + " " + p2 + " " + p3;
})
.style('fill', 'none')
.style('stroke', 'black');
</script>
</body>
</html>