将变量i传递给D3函数

时间:2017-01-13 03:02:47

标签: javascript d3.js

我在循环中运行D3。我想传递变量' i'在D3功能,但我无法这样做。这是我的代码 - 你能告诉我我做错了吗?

完美无缺

.style("fill", dataz[i].color) 

不起作用

.style("fill-opacity", function(d, i) {
            if (dataz[i].color === "#ffff") {
              return "0";
            });

完整代码

  for (i = 0; i < dataz.length; i++) {
    d3.select(list[i])
      .style("fill", dataz[i].color)
      .style("fill-opacity", function(d, i) {
        if (dataz[i].color === "#ffff") {
          return "0";
        } else {
          return "0.5"
        }
      })
  }

2 个答案:

答案 0 :(得分:1)

一般来说,使用D3时,不需要循环。考虑到D3对数据的作用,它(通常)完全没有必要。确实,我们确实在D3 dataviz中使用循环,但仅在非常特定的情况下,才能解决非常具体的问题。对于大多数情况,当我们看到使用循环的D3代码时,我们倾向于认为该代码没有正确使用D3功能(同样,在您的代码中,您将i混合在一起for循环与匿名函数中的i。它们不一样。)

因此,要使用第二个参数(即索引)访问数据数组,请忘记 for 循环:您只需要在选择中传递它。

这是一个简单的例子,使用输入选择。我们检查dataz值是否为blue。如果是,我们将不透明度设置为0.1:

&#13;
&#13;
var svg = d3.select("svg");

var dataz = ["teal", "brown", "blue", "purple"];

var circles = svg.selectAll(".circles")
    .data(dataz)
    .enter()
    .append("circle");

circles.attr("r", 20)
    .attr("cy", 50)
    .attr("cx", (d, i) => i * 50 + 40)
    .attr("fill", d => d)
    .attr("stroke", "black")
    .style("fill-opacity", (d, i) => dataz[i] === "blue" ? 0.1 : 1)
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
&#13;
&#13;
&#13;

请注意:在上面的代码段中,dataz[i]d(基准本身)相同。

解释代码问题

匿名函数中的i不是循环中的i。由于函数的范围,当您在匿名函数中执行console.log(i)时,您将记录第二个参数或索引,在此演示中始终为零:

&#13;
&#13;
var dataz = ["teal", "brown", "blue", "purple"];

for (var i = 0; i < dataz.length; i++) {
    d3.select("body").attr("fill", (d,i)=>console.log("the value of i is: " + i));
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;

一个简单的解决方案是更改for循环的变量名称(或第二个参数,它并不重要)。查看此演示,第二个参数(i)始终为零,但循环(j)从0变为3(此处不需要let,它可以正常工作与var):

&#13;
&#13;
var dataz = ["teal", "brown", "blue", "purple"];

for (var j = 0; j < dataz.length; j++) {
    d3.select("body").attr("fill", (d,i)=>console.log("second argument:" + i + " - loop:" + j));
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

忽略变量的名称(可能是其他情况下的问题),这里的问题是由于循环索引变量不存在或从D3js数据函数访问时具有不同的值。

确保在数据函数中使用当前循环值的唯一方法是在创建数据函数时提供它,因此该索引值存在于数据函数的范围内。

这应该有用(没试过!):

  for (idx = 0; idx < dataz.length; idx++) {
    d3.select(list[idx])
      .style("fill", dataz[i].color)
      // Immediately Invoked Function Expression will do the trick!
      .style("fill-opacity", (function(d, i) {
        if (dataz[idx].color === "#ffff") {
          return "0";
        } else {
          return "0.5"
        }
      })(idx));
  }