0

我有一种感觉,这对我来说是一个非常基本的误解。

我正在从这棵树可视化中工作:http: //bl.ocks.org/mbostock/4339083

当用户单击具有子节点的节点时,原始版本的节点会打开和折叠。我想这样做,以便单击没有子节点的节点具有其他效果(特别是,我希望它在另一个窗口中打开图像)。

所以,这里是分配点击功能的地方:

var nodeEnter = node.enter().append("g")
    .attr("class", "node")
    .attr("class", function(n) {
        if (n.children) {
            return "inner node"
        } else {
            return "leaf node"
        }
        })
    .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
    .on("click", click);

我添加了第二类分配来区分有子节点和没有子节点。

这是我修改后的点击功能:

function click(d) {
  if (d.attr("class") == "inner node") {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
  } else if (d.attr("class") == "leaf node") {
    // open image
  }
  update(d);
}

我添加了外部 if 语句来区分这两种节点。

所以,当我点击时,目前没有任何效果。我假设我的 'd.attr("class") == "inner node"' 出现错误,要么是因为该类属性的分配不起作用,要么是因为我写的内容是胡言乱语。但是,当我将其更改为“节点”时,它也不起作用。

我还想到,分配可能会因所有节点开始折叠的事实而被破坏 - 所以“n.children”可能会返回错误,即使有孩子。让孩子崩溃有影响吗?

非常感谢任何帮助。

- - - - - - - - - - - - - - - ** 编辑 ** - - - - - - - - ---------------

从玩了一下,我想我已经确定我应该使用“d.class”,而不是“d.attr('class')”。但是,这仍然无法正常工作。我假设我误解了 d 在这里代表什么 - 对吗?

-----------------------------** 编辑 2 **---------------- --------------

好的,我的第一次编辑是错误的。但是,多亏了祈祷者,我已将代码更改为:

function click(d) {
  if (d.children || d._children) {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
  } else {
    d3.select( this ).attr("fill", "#CCCCCC");
  }
  update(d);
}

现在可以了。然而,与我的预期相反,我改变的是文本填充,而不是圆圈填充。这是为什么?文本和圆圈是可以点击的不同区域,但无论我点击哪一个,总是会改变文本。我假设“this”指的是节点,而不是具体的圆圈或文本,那么为什么它选择一个而不是另一个呢?

4

2 回答 2

2

编辑:您正在覆盖您的课程。它应该读

var nodeEnter = node.enter().append("g")
    .attr("class", function(n) {
    if (n.children) {
        return "node inner node"
    } else {
        return "node leaf node"
    }
    });

还要注意innerandnode是两个不同的类,因为它们之间有空格。


简短的回答:看起来您正在尝试使用.attr()D3 选择以外的其他东西。

更长的答案:在 D3 的函数中,大多数情况下您有两个参数:di,其中d指的是与您的节点关联的数据,并且i是您的节点的索引。

因此,例如,内部节点上的单击处理程序如下所示:

d3.selectAll( ".inner.node" ).on( "click", function( d, i ) { /* do somehting */ });

d不是节点的 SVG 元素(“视图”),而是它背后的数据(“模型”)。因此它没有.attr()方法。要使用它,您必须选择您的视图:

d3.select( this ).attr(...);

我想这就是你的错误的根源。

但是我也想知道为什么你必须使用节点的类而不只是d.children在你的点击处理程序中检查?

于 2013-09-12T14:45:23.220 回答
1

d您在此处操作的参数是绑定到该特定元素的数据,而不是元素本身。this您可以通过选择它来访问该元素并对其执行通常的 D3 操作。也就是说,在你的click处理程序中,你可以做这样的事情。

function click() {
  if(d3.select(this).attr("class") == "inner node") {
    // do something
  }
}

文档中的更多详细信息。另一个答案向您展示了一种更好的方式来处理这些事情——您可以直接访问需要区分不同行为的数据,因此无需通过 DOM 元素进行代理。

于 2013-09-12T16:56:58.873 回答