在 d3 中标记力导向节点:速度与可见性

Posted

技术标签:

【中文标题】在 d3 中标记力导向节点:速度与可见性【英文标题】:Labeling force-directed nodes in d3: speed vs visibility 【发布时间】:2017-09-30 22:57:41 【问题描述】:

关于向 d3 力图添加标签的另一个问题...

我正在使用单个组内的节点标记图表,并且我一直在这些组内附加标签,如下所示:

<svg>
  <g class="nodes-with-labels">
    <g class="individual-node">
      <circle></circle>
      <text>Node Label</text>
    </g>
    ...
  </g>
</svg>

这会为图形添加最少的额外元素,并允许我的图形的 tick() 函数只调用一个 transform 操作。我在这里放了一个演示小提琴(没有任何动作/tick()函数): https://jsfiddle.net/52cLjxt4/1/

不幸的是,标签最终位于许多节点的后面,因为它们位于在包含节点的其他组之前绘制的组中。这个问题可以通过将节点和标签放到不同的父组中来解决,比如this example:

https://jsfiddle.net/hhwawm84/1/

<svg>
  <g class="nodes">
    <g class="individual-node">
      <circle></circle>
    </g>
    ...
  </g>
  <g class="labels">
    <g class="individual-label">
      <text>Node Label</text>
    </g>
    ...
  </g>
</svg>

但是,这似乎要慢得多:它会创建更多元素并需要两个转换语句而不是 tick() 语句中的一个,因为它是单独移动标签。

速度是我的项目真正关心的问题。这里有没有更好的方法可以避免创建这么多额外的组并将transform 语句加倍?

【问题讨论】:

【参考方案1】:

您不需要在g 中添加每个标签和圆圈 - 只需直接在每个元素上设置变换属性即可。也可能值得分析设置cx/cyx/y 属性而不是转换。

如果您不需要图表来制作动画,那么预先计算刻度并设置变换可能有助于提高性能:

for (var i = 0; i < 120; ++i) simulation.tick();

如果这仍然太慢,请尝试在 html 元素上使用 canvas(更快,因为它没有场景图)或 css 转换(更快,因为它们是gpu accelerated)。

【讨论】:

以上是关于在 d3 中标记力导向节点:速度与可见性的主要内容,如果未能解决你的问题,请参考以下文章

D3.js 网络图使用力导向布局和矩形节点

D3.js 力导向图的拖拽(drag)与缩放(zoom)

多线程—— 内存可见性

缓存一致性与可见性

杂谈高速缓存一致性与可见性

Java并发基础并发编程bug源头:可见性原子性和有序性