【 D3.js 进阶系列 — 2.2 】 力学图的参数

力学图的布局中有很多参数,本文将逐个说明。

D3 中的力学图布局是使用韦尔莱积分法计算的,这是一种用于求解牛顿运动方程的数值方法,被广泛应用于分子动力学模拟以及视频游戏中。

定义布局的代码如下:

即可,D3 中提供了 17 个函数用于设定其参数和事件,在所有布局中是最多的,下面将对其进行说明。

size()

用于设定力学图的作用范围,使用方法为 force.size( [ x , y ] ),这个函数用于指定两件事:

  • 重力的重心位置为 ( x/2 , y/2 )
  • 所有节点的初始位置限定为 [ 0 , x ] 和 [ 0 , y ] 之间(但并非之后也是如此)

如果不指定,默认为 [ 1 , 1 ] 。

linkDistance()

指定结点连接线的距离,默认为20。如果距离是一个常数,那么各连接线的长度总是固定的;如果是一个函数,那么这个函数是作用于各连接线( source , target )的。

linkStrength()

指定连接线的坚硬度,值的范围为[ 0 , 1 ],值越大越坚硬。其直观感受是:

  • 值为1,则拖动一个顶点A,与之相连的顶点会与A保持linkDistance设定的距离运动
  • 值为0,则拖动一个顶点A,与之相连的顶点不会运动,连接线会被拉长

friction()

定义摩擦系数的函数,值的范围为[ 0 , 1 ],默认为0.9。但是这个值其实并非物理意义上的摩擦,其实际意义更接近速度随时间产生的损耗,这个损耗是针对每一个顶点的。

  • 值为1,则没有速度的损耗。
  • 值为0,则速度的损耗最大。

charge()

设定顶点的电荷数。该参数决定是排斥还是吸引,默认值为-30。

  • 值为+,则相互吸引,绝对值越大吸引力越大。
  • 值为-,则相互排斥,绝对值越大排斥力越大。

chargeDistance()

设定引力的作用距离,超过这个距离,则没有引力的作用。默认值为无穷大。

gravity()

以 size 函数设定的中心产生重力,各顶点都会向中心运动,默认值为0.1。也可以设定为0,则没有重力的作用。

theta()

顶点数如果过多,计算的时间就会加大(O(n log n))。theta 就是为了限制这个计算而存在的,默认值为0.8。这个值越小,就能把计算限制得越紧。

alpha()

设定动画的冷却系数,运动过程中该系数会不断减小,直到等于0为止,此时动画也停止了。其实:

  • force.start() 是将 alpha 设定为 0.1(通过调用resume) 后开始计算的
  • force.resume() 等价于 alpha(0.1)
  • force.stop() 等价于 alpha(0)

谢谢阅读。

文档信息

【 D3.js 进阶系列 — 2.2 】 力学图的参数》上有31条评论

  1. 老师,我想知道如何同时显示多张图片,比如最开始显示了一张图片,然后点击按钮后显示另外一张图片,这张图片和之前的图片不重叠,最开始我是想通过指定force中的size来显示图片显示区域,后来发现限制不了,求老师解答

    • 当点击按钮后,向服务器发送请求,获取图片。然后更换原有图片。

      也可以一次性读入,点击的时候更换。

  2. 您好,请问如果给所有点赋一些权重,如何能实现权重越大的点离中心越近呢?

    • 这个问题是一个很有意思的问题,我认为是能做到的。但是得思考一些时间,试一下。
      如果你知道了,也请告诉我一声。

  3. 前辈可否留下更直接的联系方式,晚辈有些棘手的问题求教,关于使用了svg绘制后,是否有一些其他的标签就不能使用或者要受影响了?晚辈初涉D3,还不太了解,只知道一些js和jquery、css

  4. 你好,我现在想在已经形成的力导向图基础上继续扩展网络,实现点击节点,然后节点周围弹出一圈与之相关的节点。但是这些新出现的节点不是一开始就设置好的,二十点击事件触发了传入新数据,并在原图基础上进行补充,请问如何实现呢

  5. 老师您好,我想在力学图里面实现:力学图有两类节点,我想让两类的节点分别限制在两个区域里面,这个可以实现吗?

    • 你好,可是使用两个力学图的布局(Layout)分别控制两堆顶点。然后分别设定运动范围之类的即可。

        • 老师,还有个问题。这两类节点已经在不同的布局中,但是之间相互有联系,需要连线起来,这该怎么弄呢?

  6. JSONObject dataset = new JSONObject();
    d3.json(dataset,function(error,root){
    if( error ){
    return console.log(error);
    }
    console.log(root);
    老师,我生成了一个json,这样调用的时候报错是什么原因?很急,在线等。

    • d3.json 的第一个参数必须是文件名(地址),不能是JSONObject对象,而且如果你用 JSONObject 的话,就没有必要使用 d3.json 函数了,直接进行绘制即可。

      • json数组是{ “source”: “0”, “target”: “1” }, 有双引号
        但是原来的.json文件没有双引号,线出不来了怎么办

  7. 你好,最近看你的教程在学力图,网络上资料很少,我主要是想用这个实现一个网络拓扑图,不知道这个连接线条如何在顶端绘制箭头呢。

      • d3.select(“svg”).append(“svg:defs”).selectAll(“marker”)
        .data(root.nodes)
        .enter().append(“svg:marker”)
        .attr(“id”, “markerArrow”)
        .attr(“viewBox”, “0 5 10 10″)
        .attr(“refX”, 20)
        .attr(“refY”, -1.5)
        .attr(“markerWidth”, 6)
        .attr(“markerHeight”, 6)
        .attr(“orient”, “auto”)
        .append(“svg:path”)
        .attr(“d”, “M0,-5L10,0L0,5″);

        var edges_line = svg.selectAll(“line”)
        .data(root.edges)
        .enter()
        .append(“line”)
        .style(“stroke”, “#222020″)
        .style(“stroke-width”, 3)
        .attr(“marker-end”, “url(#markerArrow)”);
        你好,我看了一下资料,加了这个箭头的元素,可是没有效果,我是在你力图的代码上改的,就是添加上面那个marker,然后再line里面添加marker-end,是因为你这个节点是用图像,显示不出来?刚入门不太懂。

          • 你好,发现问题了,之前写的箭头是有效的,只是先画线导致箭头被盖在图片内部,我换了一下顺序,可是现在箭头是显示在内部的,就是线的终点是在图片中心,那我要怎么弄才能把箭头显示在图片的边缘。

          • 老师,我也遇到这个问题了,链接线改成箭头以后,箭头会被图片挡上,这个位置怎么调

  8. 老师终于开始讲解参数了!看来我们有福了!
    恩!我碰到一个问题,还是需要老师解惑:
    我用数组.push()向数组中添加一个对象,然后用d3.layout.force().nodes(数组)转换,但是添加进去的对象转换出来的是NaN,而数组中原本有的对象转换成功了,而这两个对象的数据都是一样的!没有想明白是什么原因!
    望老师帮助!

      • 我是自己定义了一个空的数组,然后从json文件中读取数据,push到数组中,结果出错了!一直困扰着我!

        但是我在老师的力学例子中push到数组中一个对象,确实成功的!我不明白这两者之间有什么区别!

评论已关闭。