Typescript 如何使用D3'偏移贝塞尔曲线的源点和目标点;s链接生成器?
我正在使用typescript和D3,使用D3的treeLayout,编写一个水平层次树power双自定义视觉,我需要编写一个链接生成器,可以根据用户的意愿绘制bezier、阶跃和对角链接 对我来说,问题是:由于节点是具有一定宽度的矩形,链接应该从(source.x+width/2,y)到(target.x-width/2,y)。我使用d3.line()函数(返回路径字符串)和linkHorizontal函数(返回link()函数)成功地使用了对角线和步长选项。我已经阅读了整个文档,甚至d3代码本身,但到目前为止还没有设法使用它的源、目标和上下文函数来实现我所需要的 以下是我迄今为止的代码,简化版:Typescript 如何使用D3'偏移贝塞尔曲线的源点和目标点;s链接生成器?,typescript,d3.js,powerbi-custom-visuals,Typescript,D3.js,Powerbi Custom Visuals,我正在使用typescript和D3,使用D3的treeLayout,编写一个水平层次树power双自定义视觉,我需要编写一个链接生成器,可以根据用户的意愿绘制bezier、阶跃和对角链接 对我来说,问题是:由于节点是具有一定宽度的矩形,链接应该从(source.x+width/2,y)到(target.x-width/2,y)。我使用d3.line()函数(返回路径字符串)和linkHorizontal函数(返回link()函数)成功地使用了对角线和步长选项。我已经阅读了整个文档,甚至d3代码
- 此.settings.links.style保存用户的链接选项“bezier”、“curve”或“step”
- this.settings.nodes.width保存节点的宽度
- 这个.orientation.x映射了在Bostock中看到的x和y函数(原始代码也考虑了其他方向)
下面是一个简单的Bezier曲线函数,用于代替D3:
const getBezierPath = (from, to) => {
if (Math.abs(from.x - to.x) > Math.abs(from.y - to.y)) {
const midX = (to.x + from.x) / 2;
return `M ${from.x},${from.y} C ${midX},${from.y} ${midX},${to.y} ${to.x},${to.y}`;
} else {
const midY = (to.y + from.y) / 2;
return `M ${from.x},${from.y} C ${from.x},${midY} ${to.x},${midY} ${to.x},${to.y}`;
}
};
最后,我提出了这个函数,它解决了同时使用d3.line()和d3.linkHorizontal()的问题。关键是使用d3.DefaultLinkObject的实现,这样我就可以使用attr传递的原始源和目标(“d”,f(d)) 因此,如果它能帮助任何人:
class myLinkObject implements d3.DefaultLinkObject {
public source: [number, number];
public target: [number, number];
constructor(s: [number, number], t: [number, number]) {
this.source = s;
this.target = t;
}
}
function linkGenerator(d) {
var deltaX = self.settings.nodes.width / 2;
var pSource: [number, number] = [self.orientation.x(d.source) + deltaX, self.orientation.y(d.source);
var pTarget: [number, number] = [self.orientation.x(d.target) - deltaX, self.orientation.y(d.target);
var points = [pSource, pTarget];
var linkObject: myLinkObject = new myLinkObject(pSource, pTarget);
var path = "";
if (self.settings.links.style == "step") {
var lineGenerator = d3.line().curve(d3.curveStep);
path = lineGenerator(points);
} else if (self.settings.links.style == "diagonal") {
var lineGenerator = d3.line();
path = lineGenerator(points);
} else { // bezier
var linkGen = d3.linkHorizontal().x(d => d[0]).y(d => d[1]);
path = linkGen(linkObject);
}
return path;
}
谢谢,这很有帮助@EduardoWaghabi请将答案标记为正确
class myLinkObject implements d3.DefaultLinkObject {
public source: [number, number];
public target: [number, number];
constructor(s: [number, number], t: [number, number]) {
this.source = s;
this.target = t;
}
}
function linkGenerator(d) {
var deltaX = self.settings.nodes.width / 2;
var pSource: [number, number] = [self.orientation.x(d.source) + deltaX, self.orientation.y(d.source);
var pTarget: [number, number] = [self.orientation.x(d.target) - deltaX, self.orientation.y(d.target);
var points = [pSource, pTarget];
var linkObject: myLinkObject = new myLinkObject(pSource, pTarget);
var path = "";
if (self.settings.links.style == "step") {
var lineGenerator = d3.line().curve(d3.curveStep);
path = lineGenerator(points);
} else if (self.settings.links.style == "diagonal") {
var lineGenerator = d3.line();
path = lineGenerator(points);
} else { // bezier
var linkGen = d3.linkHorizontal().x(d => d[0]).y(d => d[1]);
path = linkGen(linkObject);
}
return path;
}