如何修复 d3 中的这个切换功能?

How to fix this toggle function in d3?

我这里有两个问题:

1/ 这些按钮(您可以 运行 下面的代码片段)应该在第二次点击时恢复到原来的不透明度,但它们没有!有人可以向我解释代码有什么问题吗?

2/ 如何在第二次点击时返回 text 之前的颜色 而无需在切换功能中定义之前的颜色(再次!) . ?

解释:正如您在 运行 执行以下代码片段时看到的那样,text (1,2,3...) 在第一个 [=17] 处变为 white =].我想在第二次点击时将它设置回原来的颜色,而不必写:

var newTextFill = active ? "white" : "**former_color**";

例如,在 this example 中,作者没有指定 font-size 图例应该 return 在第二次点击时出现,但你可以看到它缩小回原来的样子尺寸。我怎样才能在这里对字体颜色做同样的事情?

 var name = ["123456789"];
 
 
 var color = d3.scaleOrdinal()
               .range(["#00baff", "#0014fe", "#00dbaf", "#f4bf02", "#ffa600",                        "#ff0000", "#ff00c4", "#ee693e", "#99958f"]);
 
 
 var svg = d3.select("body")
             .append("svg")
             .attr("width", 300)
             .attr("height",300)
 
 var legende = svg.selectAll("bar")
                  .data(name)
                  .enter()
                  .append("g")
                  .attr("x",  0)
                  .attr("y", function (d,i) {return 12 + i * 20})

    legende.append("text")
           .text(function(d,i) { return name[i]})
           .attr("class", "legtext")
           .style("font-family", "helvetica")
           .style("fill-opacity", 0.8)
           .attr("x",  4)
           .attr("y", function (d,i) {return 12 + i * 20})
           .style("font-size", 10)
           .style("fill", function(d,i) { return color(i)})
           .style("text-decoration", "none")
           .style("opacity", 1);

    legende.append("rect")
           .attr("class", "recta")
           .attr("x",  2)
           .attr("y", function (d,i) {return 1 + i * 20})
           .attr("width", 65)
           .attr("height", 15)
           .style("fill", function(d,i) { return color(i)})
           .style("opacity", 0.09);

    legende.append("rect")
           .attr("class", "rectastroke")
           .attr("id", function(d,i) {return "str" + i})
           .attr("x",  2)
           .attr("y", function (d,i) {return 1 + i * 20})
           .attr("width", 65)
           .attr("height", 15)
           .style("stroke", function(d,i) { return color(i)})
           .style("stroke-width", 0.5) 
           .style("fill", "none")
           .attr("display", "none");
           
           
           
    legende.on("click", function (d,i) 
               {var active = d.active ? false : true;
                var newOpacity = active ? 1 : 0.1;
                var newTextFill = active ? "white" : "blue";
               
               d3.select(this)
                 .select("rect")
                 .style("opacity", newOpacity)
                 
                 
               d3.select(this)
                 .select("text")
                 .style("fill", newTextFill)
                 .raise()
                 
               d.active = active  });  
           
           
           
           
    legende.on("mouseover", function(d, i)      
        {d3.select(this).selectAll(".rectastroke").attr("display", "true")});
        
    legende.on("mouseout", function(d, i)      
        {d3.select(this).selectAll(".rectastroke").attr("display", "none")});    
body {font-family: 'Open Sans', sans-serif;
          font-size: 11px;
          font-weight: 300;
          fill: #242424;
          text-align: center;
          cursor: default;}
          
     .legende {cursor: pointer;}
     .recta {cursor: pointer;}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>


  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>

   

<body>
     <div class="colored buttons"></div>
</body>
</html>

在您链接的 bl.ocks 中,她实际上指定了图例在第二次单击时 return 的字体大小...在 CSS.

发生的事情是,如果 active 为假,则 setter 将 return undefined...

d3.select(this)
    .style("font-size", function() {
        if (active) {return "25px"}
    })

... 并且UA会根据CSS.

设置样式

您可以在不指定任何矩形的情况下对矩形执行相同的操作 newOpacity:

d3.select(this)
    .select("rect")
    .style("opacity", function() {
        if (active) return 1;
    })

这是演示:

var data = "123456789".split("").map(function(d) {
  return {
    value: d
  }
});

var color = d3.scaleOrdinal()
  .range(["#00baff", "#0014fe", "#00dbaf", "#f4bf02", "#ffa600", "#ff0000", "#ff00c4", "#ee693e", "#99958f"]);

var svg = d3.select("body")
  .append("svg")
  .attr("width", 300)
  .attr("height", 300)

var legende = svg.selectAll("bar")
  .data(data)
  .enter()
  .append("g")
  .attr("x", 0)
  .attr("y", function(d, i) {
    return 12 + i * 20
  })

legende.append("text")
  .text(function(d, i) {
    return d.value
  })
  .attr("class", "legtext")
  .style("font-family", "helvetica")
  .style("fill-opacity", 0.8)
  .attr("x", 4)
  .attr("y", function(d, i) {
    return 12 + i * 20
  })
  .style("font-size", 10)
  .style("fill", function(d, i) {
    return color(i)
  })
  .style("text-decoration", "none")
  .style("opacity", 1);

legende.append("rect")
  .attr("class", "recta")
  .attr("x", 2)
  .attr("y", function(d, i) {
    return 1 + i * 20
  })
  .attr("width", 65)
  .attr("height", 15)
  .style("fill", function(d, i) {
    return color(i)
  });

legende.on("click", function(d, i) {
  var active = d.active ? false : true;

  d3.select(this)
    .select("rect")
    .style("opacity", function() {
      if (active) return 1;
    })

  d3.select(this)
    .select("text")
    .style("fill", function(e, j) {
      if (active) {
        return "white";
      } else {
        return color(i)
      }
    })
    .raise()

  d.active = active
});
.legende {
  cursor: pointer;
}

.recta {
  opacity: 0.1;
  cursor: pointer;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

然而,对于文本颜色,由于您未在 CSS 中指定它,因此您必须使用正常的 if...else 代码。