4

在之前的一篇名为“ D3:如何为 Force Directed Graphs FDG 中的节点创建圆的缓慢过渡? ”的帖子中,我得到了关于如何在 D3 中过渡单个元素(例如“仅圆”的半径)的一个很好的答案。

我的后续问题现在是关于如何同时转换“多个 D3 属性”......

提醒一下,我正在使用 D3 生成的单选按钮将 FDG 布局中的节点大小(通过鼠标单击)从默认大小切换到缩放大小。您可以在节点集群图的左上角找到单选按钮( http://nounz.if4it.com/Nouns/Applications/A__Application_1.NodeCluster.html )

在默认数字和缩放幅度(现在使用转换)之间切换节点圆的代码如下所示......

    var densityControlClick = function() {

      var thisObject = d3.select(this);
      var typeValue = thisObject.attr("density_type");
      var oppositeTypeValue = (function() {
        if(typeValue=="On") {
          return "Off";
        } else {
          return "On";
        }
      })();

      var densityBulletSelector = "." + "densityControlBullet-" + typeValue;
      var selectedBullet = d3.selectAll(densityBulletSelector);
      selectedBullet.style("fill", "Black") 

      var oppositeDensityBulletSelector = "." + "densityControlBullet-" + oppositeTypeValue;
      var selectedOppositeBullet = d3.selectAll(oppositeDensityBulletSelector);
      selectedOppositeBullet.style("fill", "White") 

      if(typeValue=="On") {
        var selectedNodeCircles = d3.selectAll("#NODE");
        selectedNodeCircles.transition().duration(500).attr("r", function(d){ return rRange(d.rSize); });
      }
      else {
        var selectedNodeCircles = d3.selectAll("#NODE");            selectedNodeCircles.transition().duration(500).attr("r", function(d) { if (d.id==focalNodeID) { return centerNodeSize; } else { return defaultNodeSize; } } );
      }

    }

一切都很好,当您选择单选按钮时,您可以看到较慢的节点转换。但是,我现在想学习如何同时转换多个元素,例如半径和边长,以及这样做的背后的理论,以展示 D3 的动态特性。

我的问题是:鉴于我已经可以成功过渡圆的半径,我将如何过渡其他元素,如基于“alpha”、“摩擦”等属性的边长,以及......背后的理论是什么转换多个元素(换句话说,代码是什么意思,英文)?D3 API 似乎并没有清楚地进入同时转换多个属性背后的理论。

4

1 回答 1

4

所以转换多个属性是这个问题的简单部分。就像常规选择一样,您可以在过渡时一次设置多个属性:

selectedNodeCircles.transition().duration(500)
    .attr("r", function(d){ return rRange(d.rSize); })
    .attr("stroke", 'red');

这将转换您的半径和线条颜色。转换是 DOM 元素(在本例中为圆形)的一个属性,它将转换任意数量的 DOM 属性。需要记住的是,每个 DOM 元素上只有一个转换对象。因此,如果您创建另一个,您将覆盖旧的。

// This will NOT work
circles.transition().duration(1000).attr('r', 50);
// The radius transition will be overridden by the fill 
// transition and so will not complete
circles.transition().duration(1000).attr('fill', 'red');

这实际上非常有用,因为您不必担心中断正在进行的动画并弄清楚它们的距离然后开始新的动画 - 这通常会自动处理。

在您的情况下,您希望在图表中转换边长。这些是由节点的位置属性决定的。从您的成品来看,这些属性已经被动画化了,因为您可能在 tick() 回调中在布局算法的每次迭代(而不是通过转换)上更新 DOM。

因此,您可以在刻度回调中使用转换,这可能看起来很奇怪,并且可能很麻烦与半径转换保持同步(您必须在转换中设置这两个属性)。但这可能正是您所需要的。

或者,如果您可以等待,请不要在 tick 回调中更新 DOM。让布局完成 - 当它不在每个刻度上渲染时它运行得更快 - 一旦完成,您可以将半径和 x 和 y 属性设置为它们的最终位置。当然,这意味着您需要良好的起始位置。

于 2013-07-15T17:35:13.493 回答