转换后,d3.select()不会立即生效

时间:2016-04-29 14:11:43

标签: javascript d3.js

我一直在努力使一段文字可点击。我可以使其他文本可单击,并且单击此文本后该函数的行为与预期一致。麻烦的文本嵌套在某些东西中,我认为这就是为什么它与.on()的行为不一样。我在文本片段中添加了id以便于选择。

现在我终于有了一段代码,使文本可以点击,一切都按预期运行 - 但只有在Chrome开发者控制台中输入时才会这样做! :

d3.select("#patext").on("click", function() {toggleLine();})

在Chrome控制台中输入后,一切正常,但在index.html文件中却无效。 &#39; patext&#39;是我之前给它的id。 index.html在顶部包含<style></style>部分,然后在<body></body>下面。在体内有两个<script></script>第一个加载d3.js第二个是我的脚本。上面的d3.select()行恰好位于toggleLine()的函数定义之下。

已经完成了建议herehere并且我的脚本在正文和脚本中加载d3是一个单独的主脚本。有什么想法吗?

根据要求,以下是基于Bostock脚本的原始240行中的80行,希望我没有删除任何重要内容

<!DOCTYPE html>
<meta charset="utf-8">
<style>

body {
  font: 10px sans-serif;
/*  background-color: #ffeda0;*/
}
.axis path
</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
var parseDate = d3.time.format("%Y-%m-%d").parse;
var x = d3.time.scale().range([0, width]);
var svg = d3.select("body").append("svg")
    .attr("width", width + margin.left + margin.right)
d3.csv("myfile.csv", function(error, data) {
  if (error) throw error;
  color.domain(d3.keys(data[0]).filter(function(key) { return key !== "date"; }));
  data.forEach(function(d) { 
    d.date = parseDate(d.date);
  });
  var cities = color.domain().map(function(name) {
    return {
      name: name,
      values: data.map(function(d) {
        return {date: d.date, temperature: +d[name]};  // plus casts a string '55' to a number 55
      })
    };
  });

  x.domain(d3.extent(data, function(d) { return d.date; }));

  y.domain([
    d3.min(cities, function(c) { return d3.min(c.values, function(v) { return v.temperature; }); }),
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.temperature; }); })
  ]);

  svg.append("rect")     // fill it a colour
    .attr("width", 830)
    .attr("height", "100%")
    .attr("fill", "AliceBlue");    

  svg.append("g")
    .classed("axis x", true) 
    .call(xAxis2);

  var city = svg.selectAll(".city")
      .data(cities)
      .enter().append("g")
      .attr("class", "city");

  city.append("path")
      .style("stroke", function(d) {return color(d.name); })    
      .attr("class", "line")
      .attr("id", function(d) {console.log((d.name).slice(0,3));return (d.name).slice(0,3);})  // for click fn below.

  city.append("text")
      .datum(function(d) { return {name: d.name, value: d.values[d.values.length - 1]}; })
      .style("stroke", function(d) {return color(d.name); })   
      .transition()      
      .attr("x", 3)
      .attr("dy", ".35em")
      .text(function(d) { return d.name; })
      .attr("id", function(d) {console.log((d.name).slice(0,2)+"text");return ((d.name).slice(0,2)+"text");})  // for click fn
});

function toggleLine() {
    var active   = gol.active ? false : true,
                newOpacity = active ? 0 : 1;
            d3.select("#gol").style("opacity", newOpacity);
            gol.active = active;}

document.addEventListener("DOMContentLoaded", function(event) { 
    //... your code
    d3.select("#patext").on("click", function() {toggleLine();});
    //... more of your code
});
</script> 
</body>

1 个答案:

答案 0 :(得分:2)

原来有一个transition并且延迟了DOM操作,这使得事件监听器在创建DOM元素之前绑定。

  

过渡是一种特殊类型的选择,操作员可以随着时间的推移而不是瞬间应用。您可以使用转换运算符从选择中转换。虽然转换通常支持与选择相同的运算符(例如attr和style),但并不支持所有运算符;例如,您必须在转换开始之前附加元素。提供了一个删除操作符,以便在转换结束时方便地删除元素。

解决方案是在click之前绑定transition()侦听器。

<body>
  <script src="//d3js.org/d3.v3.min.js"></script>
  <script>

    function toggleLine() {
      var active = gol.active ? false : true,
        newOpacity = active ? 0 : 1;
      d3.select("#gol").style("opacity", newOpacity);
      gol.active = active;
    }

    document.addEventListener("DOMContentLoaded", function(event) {
      var parseDate = d3.time.format("%Y-%m-%d").parse;
      var x = d3.time.scale().range([0, width]);
      var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
      d3.csv("myfile.csv", function(error, data) {
        if (error) throw error;
        // ...

        city.append("text")
          .datum(function(d) {
            return {
              name: d.name,
              value: d.values[d.values.length - 1]
            };
          })
          .attr("id", function(d) {
            console.log((d.name).slice(0, 2) + "text");
            return ((d.name).slice(0, 2) + "text");
          });  // for click fn
          // bind listener before transition
          .on("click", function(d){
              if(d3.select(this).attr('id') === "patext") {
              toggleLine();
           }
          .style("stroke", function(d) {
            return color(d.name);
          })
          .transition() 
          .attr("x", 3)
          .attr("dy", ".35em")
          .text(function(d) {
            return d.name;
          })
      });

    });
  </script>
</body>

这允许在完全加载DOM后执行代码。

有关实现此目的的其他选项,请参阅$(document).ready equivalent without jQuery