更新模式D3

时间:2015-08-23 18:14:32

标签: d3.js

我想了解D3中的更新模式。我有一个DOM,我想"更新"基于时间/日期滑块。我无法理解如何删除我的文本并将其替换为" new"文本。代码现在正在运行的方式是它将我的文本放在一条长行中,而不是在我更改滑块时显示每个新的文本值。请在代码中查看我的内联评论,以了解我认为我遇到问题的地方。

function drawMonthN(m, nuc, tween){    
   //console.log("m is updating: " + m) 
   //my function is working, it's updating my month

   //console.log("what is nuc: " + JSON.stringify(nuc));
   //as an example it loads my array ([{"time":"Jun-13","yearTotal":33, "Jun-13":4000},{"time":"Jul-13", "yearTotal":44,....)

var svg = d3.select('#num')
        .append("g2")
        .attr('width', 150)
        .attr('height', 20)
        .append("g")
        .attr("transform", "translate(0,0)");

update(nuc);

function update(data){
    var text = svg.selectAll("text")
            .data(data, function(d, i){
                 //console.log("what is d:  " + JSON.stringify(d.yearTotal));
              return d.yearTotal; });
                //d.yearTotal returns all the totals and display it as a long line of text in the DOM.
          .enter().append("text")
          .attr("class", "enter")
          .attr("dy", ".75em")
          .style("fill-opacity", 1e-6)
          .text(function(d) { 
           return d.yearTotal; })  
        .transition()
          .duration(750)
          .attr("y", 0)
          .style("fill-opacity", 1);

  // EXIT
  // Remove old elements as needed.
  g2.exit().remove();
}

} // end of drawMonth function

根据我的模拟数据,我使用它是#num中显示的内容: ' 334353' 我想! 33'要显示,然后我们将仪表板更改为下个月我希望' 43'等等。

nuc = 
     [
      {
        "year": "2013",
        "time":"Jun-13",
        "yearTotal": "33",
        "LAT":11.7885,
        "LON":-144.942,
        "Jun-13":4000
      },
      {
        "year": "2013",
        "time":"Jul-13",
        "yearTotal": "43",
        "LAT":52.4378,
        "LON":-50.1609,
        "Jul-13":5000
      },
      {
        "year": "2013",
        "time":"Aug-13",
        "yearTotal": "53",
        "LAT":60.8248,
        "LON":-87.8296,
        "Aug-13":10000
      }
    ]

2 个答案:

答案 0 :(得分:1)

d3选择和数据绑定是关于处理数据数组并显示数组中每个数据的内容。绑定数组,当数据进入,退出或更新时,您将对其执行操作。但是,在您的情况下,您只想显示一个只包含一个数据的文本元素。您只需要数组中的一个数据。我只想创建一个文本元素,然后你.datum来切换数据:

// create a single text element
svg.append('text')
  .attr("class", "enter")
  .attr("dy", ".75em")
  .style("fill-opacity", 1e-6);

// update function
function update() {

  // get value from slider
  var val = +d3.select('#myRange').node().value;

  // select our one text element
  d3.select('.enter')
    .datum(nuc[val]) // use datum to assign our one piece of data
    .text(function(d) {
      return d.yearTotal;
    }) // update text
    .style("fill-opacity", 0) // hide so it fades in
    .transition()
    .duration(750)
    .attr("y", 0)
    .style("fill-opacity", 1);

这里有一些工作代码:



<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
  <link rel="stylesheet" href="style.css" />
  <script src="script.js"></script>
</head>

<body>
  
  <input type="range" id="myRange" max="2" min="0" step="1">
  
  <script>
    var nuc = [{
      "year": "2013",
      "time": "Jun-13",
      "yearTotal": "33",
      "LAT": 11.7885,
      "LON": -144.942,
      "Jun-13": 4000
    }, {
      "year": "2013",
      "time": "Jul-13",
      "yearTotal": "43",
      "LAT": 52.4378,
      "LON": -50.1609,
      "Jul-13": 5000
    }, {
      "year": "2013",
      "time": "Aug-13",
      "yearTotal": "53",
      "LAT": 60.8248,
      "LON": -87.8296,
      "Aug-13": 10000
    }]

    d3.select('#myRange')
      .on('change',function(){
        update();
      })

    var svg = d3.select('body')
      .append('svg')
      .attr('width',500)
      .attr('height',500);
      
    svg.append('text')
      .attr("class", "enter")
      .attr("dy", ".75em")
      .style("fill-opacity", 1e-6);

    function update() {
      
      var val = +d3.select('#myRange').node().value;

      d3.select('.enter')
        .datum(nuc[val])
        .text(function(d) {
          return d.yearTotal;
        })
        .style("fill-opacity", 0)
        .transition()
        .duration(750)
        .attr("y", 0)
        .style("fill-opacity", 1);
    }
    
    update();
  </script>
</body>

</html>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

如果有人感兴趣,您也可以使用常规更新模式,如下所示:

&#13;
&#13;
  var nuc = [{
    "year": "2013",
    "time": "Jun-13",
    "yearTotal": "33",
    "LAT": 11.7885,
    "LON": -144.942,
    "Jun-13": 4000
  }, {
    "year": "2013",
    "time": "Jul-13",
    "yearTotal": "43",
    "LAT": 52.4378,
    "LON": -50.1609,
    "Jul-13": 5000
  }, {
    "year": "2013",
    "time": "Aug-13",
    "yearTotal": "53",
    "LAT": 60.8248,
    "LON": -87.8296,
    "Aug-13": 10000
  }]

  var svg = d3.select('body')
    .append('svg')
    .attr('width',200)
    .attr('height',100),
    result = Range("body #myRange", "text")(nuc);
  alert("initial value is " + result());

  function Range(input, output){
    var data, update,
        range = d3.select(input)
          .on('change',function(){
        refresh.call(this);
      }),
        val = range.property("value");
    function accessor(d) {
      return d[val].yearTotal;
    }
    function refresh(v) {
      val = v || this.value;
      update = svg.selectAll(output).data([data]);
      var enter = update.enter().append('text')
        .attr("class", "enter")
        .attr("dy", ".75em")
        .style("fill-opacity", 1e-6);

      update.text(accessor)
        .style("fill-opacity", 0)
        .transition()
        .duration(750)
        .attr("y", 0)
        .style("fill-opacity", 1);
    }
    return function(_){
      data = _;
      refresh(range.property("value"));
      return accessor.bind(null, data);
    }
  }
&#13;
    #myRange {
      display: block;
    }
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<input type="range" id="myRange" max="2" min="0" step="1">
&#13;
&#13;
&#13;

要点

更新选择仅包含一个元素,因为数据包含在数组中。

update = svg.selectAll(output).data([data]);

然而,该元素将整个数据数组绑定到它,因此您可以执行此操作...

  update.text(function (d) {
      return d[val].yearTotal;
  })