d3.js:如何在网络可视化中将边从线转换为弯曲路径?

时间:2014-08-31 19:15:33

标签: svg d3.js geometry visualization spline

我有一个d3网络,其中点通过线连接。我想用弯曲的SVG路径替换线条。我忘记了数学来计算控制点的坐标。有谁知道怎么做?

例如,请看下面的图片:

Example diagram of spline math

存在A点和B点。我现在用L线连接它们。我想用曲线C代替L.为了做到这一点,我需要找到一条垂直于中点的线。线L,长度为M(长度设置为L的百分比),作为样条C的控制点。然后我需要定义一个SVG路径来定义C。

如何在d3中使用SVG执行此操作?我很久以前就已经在拉斐尔/ SVG做过这个了,但数学让我感到安慰。而且我不确定它在D3中是如何完成的。

1 个答案:

答案 0 :(得分:9)

为了让别人清楚,我们所说的是二次贝塞尔曲线。这使得两个点之间的曲线平滑,只有一个控制点。

基本方法是:

  1. 找到你的A-B中点,称之为J。
  2. 做一些触发以找到线段M末尾的点,称之为K
  3. 使用SVG Q或T路径命令绘制二次贝塞尔曲线,从A开始,到达B,控制点K.(请注意,这看起来与图表完全一样,但可以通过改变M的长度来调整。
  4. enter image description here

    这是一个javascript函数,用于返回您需要的路径:

    function draw_curve(Ax, Ay, Bx, By, M) {
    
        // Find midpoint J
        var Jx = Ax + (Bx - Ax) / 2
        var Jy = Ay + (By - Ay) / 2
    
        // We need a and b to find theta, and we need to know the sign of each to make sure that the orientation is correct.
        var a = Bx - Ax
        var asign = (a < 0 ? -1 : 1)
        var b = By - Ay
        var bsign = (b < 0 ? -1 : 1)
        var theta = Math.atan(b / a)
    
        // Find the point that's perpendicular to J on side
        var costheta = asign * Math.cos(theta)
        var sintheta = asign * Math.sin(theta)
    
        // Find c and d
        var c = M * sintheta
        var d = M * costheta
    
        // Use c and d to find Kx and Ky
        var Kx = Jx - c
        var Ky = Jy + d
    
        return "M" + Ax + "," + Ay +
               "Q" + Kx + "," + Ky +
               " " + Bx + "," + By
    }
    

    您可以在this jsfiddle处看到这一点。

    编辑:如果二次曲线不合适,您可以非常轻松地调整函数以进行三次贝塞尔曲线或弧段。