如何使用linkRadial在两点之间绘制链接?

Iro*_*Man 5 javascript d3.js

我需要在圆上的点和聚集在所述圆中心的点之间手动绘制一些链接。我有源点和目标点的 x,y 对,但我不想要它们之间的简单直线;我想要一条曲线(类似于树图中的链接)。我可以使用linkHorizontalorlinkVertical但它们的切线是恒定的;我想使用linkRadial并让切线成为该特定弧点处的径向线(我也有该弧度)。

linkRadial虽然我不明白API;它需要一个角度和一个半径,而不是一个 x 或 y 点。我如何将我的两个 x,y 对(和径向线角度)转换为期望的角度和半径?

Ger*_*ado 6

由于您有一个包含xy位置的数据数组(“我有源点和目标点的 x,y 对”),因此您必须将它们转换为angleradius。让我们看看怎么做。

首先,让我们看一个固定坐标的例子。例如,假设您有这个数据数组,具有xy位置:

var data = [{
    source: {y: 150,x: 75
    },
    target: {y: 300,x: 0
    }
}, {
    source: {y: 150,x: 75
    },
    target: {y: 0,x: 0
    }
}, {
    source: {y: 150,x: 75
    },
    target: {y: 150,x: 150
    }
}, ];
Run Code Online (Sandbox Code Playgroud)

使用此链接生成器...

var link = d3.linkHorizontal()
    .x(function(d) {
        return d.y;
    })
    .y(function(d) {
        return d.x;
    });
Run Code Online (Sandbox Code Playgroud)

...你会有一个这样的图表:

var data = [{
    source: {y: 150,x: 75
    },
    target: {y: 300,x: 0
    }
}, {
    source: {y: 150,x: 75
    },
    target: {y: 0,x: 0
    }
}, {
    source: {y: 150,x: 75
    },
    target: {y: 150,x: 150
    }
}, ];
Run Code Online (Sandbox Code Playgroud)
var link = d3.linkHorizontal()
    .x(function(d) {
        return d.y;
    })
    .y(function(d) {
        return d.x;
    });
Run Code Online (Sandbox Code Playgroud)

我们如何将其转换为可用于的数据集d3.linkRadial()

一种选择是迭代每个对象,使用基本三角函数来填充angleradius属性:

var radialData = data.map(function(d) {
    return {
        source: {
            x: 0,
            y: 0
        },
        target: {
            x: Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) - Math.PI,
            y: Math.sqrt((d.target.x - d.source.x) * (d.target.x - d.source.x) + (d.target.y - d.source.y) * (d.target.y - d.source.y))
        }
    };
});
Run Code Online (Sandbox Code Playgroud)

然后,使用此链接生成器:

var linkRadial = d3.linkRadial()
    .angle(function(d) {
        console.log(d)
        return d.x;
    })
    .radius(function(d) {
        return d.y;
    });
Run Code Online (Sandbox Code Playgroud)

我们会有这个:

var data = [{
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 300,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 0,
    x: 0
  }
}, {
  source: {
    y: 150,
    x: 75
  },
  target: {
    y: 150,
    x: 150
  }
}, ];

var svg = d3.select("svg");

var link = d3.linkHorizontal()
  .x(function(d) {
    return d.y;
  })
  .y(function(d) {
    return d.x;
  });

svg.selectAll(null)
  .data(data)
  .enter()
  .append("path")
  .attr("fill", "none")
  .attr("stroke", "blue")
  .attr("d", link);
Run Code Online (Sandbox Code Playgroud)
<script src="https://d3js.org/d3.v4.js"></script>
<svg></svg>
Run Code Online (Sandbox Code Playgroud)

现在将两个生成器放在一起,以进行比较:

var radialData = data.map(function(d) {
    return {
        source: {
            x: 0,
            y: 0
        },
        target: {
            x: Math.atan2(d.target.y - d.source.y, d.target.x - d.source.x) - Math.PI,
            y: Math.sqrt((d.target.x - d.source.x) * (d.target.x - d.source.x) + (d.target.y - d.source.y) * (d.target.y - d.source.y))
        }
    };
});
Run Code Online (Sandbox Code Playgroud)
var linkRadial = d3.linkRadial()
    .angle(function(d) {
        console.log(d)
        return d.x;
    })
    .radius(function(d) {
        return d.y;
    });
Run Code Online (Sandbox Code Playgroud)