代码之家  ›  专栏  ›  技术社区  ›  ofey

D3删除之前更新数据时的条形图

  •  0
  • ofey  · 技术社区  · 9 年前

    gh-pages ,您需要使用下拉菜单才能开始。此时,第一个数据文件data1。json未加载。

    当文件加载时,仅显示与上一次渲染中的名称相关联的条形图。再次单击下拉菜单中的同一个文件时,会出现其他条。因此,文件必须点击两次才能正确显示。

    如果初始呈现仅显示公共条,则这解释了为什么第一次加载页面时它是空白的,而没有公共条。

    无论如何,显然这不是我想要的行为。

    代码打开了 github jsFiddle

              var newRects0 = g0.selectAll(".bar")
                .data(data, function(d) {
                  return d.name;
                });
    
              // newRects0.selectAll(".bar").remove();
              newRects0.enter()
                .append('rect')
                .attr('x', function(d, i) {
                  return x(d.name);
                })
                // .attr('opacity', 0.33)
                .attr('width', x.bandwidth())
                .attr('y', height)
                .attr('height', 0)
                .attr("transform", "translate(0,0)")
                .style('fill', 'gray')
                .attr("class", function(d, i) {
                  return "group" + i + " bar"
                });
    
              newRects0.exit().remove();
    
              newRects0.transition()
                .duration(100)
                .delay(function(d, i) {
                  return i * 15
                })
                .attr("x", function(d) {
                  return x(d.name);
                })
                .attr("y", function(d, i) {
                  return y(d.clocktime);
                })
                .attr("height", function(d, i) {
                  return height - y(d.clocktime)
                })
                .attr("width", x.bandwidth());
    

    更新:

    我现在想用博斯托克的 Update Pattern III

    我已经大大简化了代码,现在已经开始了 github gh页面 jsFiddle .

     <!DOCTYPE html>
    <meta charset="utf-8">
    <style>
      .container {
        margin-left: 0px;
      }
    </style>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" crossorigin="anonymous">
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" crossorigin="anonymous"></script>
    
    <body>
      <ul class="nav nav-tabs">
        <li class="nav-item">
          <a class="nav-link active" href="#">Home</a>
        </li>
        <li class="nav-item dropdown">
          <a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false">Data</a>
          <div class="dropdown-menu">
            <a class="dropdown-item" id="defaultInput" value="one" href="#">data1.json</a>
            <a class="dropdown-item" id="updateInput" value="two" href="#">data2.json</a>
          </div>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="#">Link</a>
        </li>
        <li class="nav-item">
          <a class="nav-link disabled" href="#">Disabled</a>
        </li>
      </ul>
      <div class="container-fluid">
        <div class="row">
          <div class="col-md-12">
            <div id="race_graph">
            </div>
          </div>
        </div>
      </div>
    
      <script src="https://d3js.org/d3.v4.min.js"></script>
      <script>
        // set the dimensions and margins of the graph
        var margin = {
            top: 70,
            right: 50,
            bottom: 100,
            left: 80
          },
          width = 1400 - margin.left - margin.right,
          height = 600 - margin.top - margin.bottom;
    
        var parseTime = d3.timeParse("%M:%S");
        var timeformat = d3.timeFormat("%M:%S");
    
        // set the domains and ranges
        var x = d3.scaleBand()
          .range([0, width])
          .padding([0.6]);
    
        // temporal y-scale
        var y = d3.scaleTime()
          .range([height, 0]);
    
        var xAxis = d3.axisBottom(x);
    
        var yAxis = d3.axisLeft(y)
          .ticks(7)
          .tickFormat(d3.timeFormat("%M:%S"));
    
        // Add main graph svg
        var svg = d3.select("#race_graph")
          .append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom);
    
        // Add groups for main bar chart
        var g0 = svg.append("g")
          .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
    
        function defaultFunction() {
          d3.json("data1.json", function(error, newdata) {
            if (error) throw error;
            data = newdata;
    
            data.forEach(function(d) {
              d.racetime = parseTime(d.racetime);
              d.handicap = parseTime(d.handicap);
              d.clocktime = parseTime(d.clocktime);
              d.place = +d.place;
              d.points = +d.points;
              d.raceplace = +d.raceplace;
              d.timeplace = +d.timeplace;
            })
            update();
          });
        }
    
        function updateFunction() {
          d3.json("data2.json", function(error, newdata) {
            if (error) throw error;
            data = newdata;
            data.forEach(function(d) {
              d.racetime = parseTime(d.racetime);
              d.handicap = parseTime(d.handicap);
              d.clocktime = parseTime(d.clocktime);
              d.place = +d.place;
              d.points = +d.points;
              d.raceplace = +d.raceplace;
              d.timeplace = +d.timeplace;
            })
            update(data);
          });
        }
    
        function update(err, newdata) {
    
          // set the domains
          x.domain(data.map(function(d) {
            return d.name
          }));
    
          // set domain temporal y-scale
          y.domain([parseTime('00:00'), d3.max(data, function(d) {
            return d.clocktime
          })]);
    
          // Add the X Axis
          svg.select(".x.axis").call(xAxis);
          svg.select(".x.axis").remove();
          svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(" + (margin.left) + "," + (height + margin.top) + ")")
            .call(xAxis)
            .selectAll("text")
            .attr("transform", "translate(-100,0)")
            .style("text-anchor", "end")
            .style("font", "7px times")
            .attr("class", function(d, i) {
              return "groupText" + i + " xAxisText"
            })
            .attr("dx", "-.8em")
            .attr("dy", ".15em")
            .attr("transform", "rotate(-75)");
    
          // Add the y axis on left
          svg.select(".y.axis").remove();
          svg.append("g")
            .attr("class", "y axis")
            .attr("transform", "translate(" + (margin.left) + "," + margin.top + ")")
            .call(yAxis);
    
          var t = d3.transition()
            .duration(4000);
    
          // JOIN new data with old elements
          var newRects0 = g0.selectAll(".bar")
            .data(data, function(d) {
              return d;
            });
    
          // EXIT old elements not present in new data
          newRects0.exit()
            .transition(t)
            .attr("x", function(d) {
              return x(d.name);
            })
            .attr("y", function(d, i) {
              return y(d.clocktime);
            })
            .attr("height", function(d, i) {
              return height - y(d.clocktime)
            })
            // .attr("width", x.bandwidth())
            .remove();
    
          // UPDATE old elements present in new data
          newRects0.attr("x", function(d) {
              return x(d.name);
            })
            .attr("y", function(d, i) {
              return y(d.clocktime);
            })
            .attr("height", function(d, i) {
              return height - y(d.clocktime)
            })
            // .attr("width", x.bandwidth())
            .style('fill', 'gray');
    
          // ENTER new elements present in new data
          newRects0.enter()
            .append('rect')
            .attr("x", function(d) {
              return x(d.name);
            })
            .attr("y", function(d, i) {
              return y(d.clocktime);
            })
            .attr("height", function(d, i) {
              return height - y(d.clocktime)
            })
            .attr("width", x.bandwidth())
            .style('fill', 'gray')
            .attr("class", function(d, i) {
              return "group" + i + " bar"
            });
    
        }; //closes update() function
    
        document.getElementById("defaultInput")
          .onclick = defaultFunction;
        document.getElementById("updateInput")
          .onclick = updateFunction;
        defaultFunction();
      </script>
    </body>
    

    谢谢

    2 回复  |  直到 9 年前
        1
  •  1
  •   ofey    9 年前

    我终于想出了博斯托克的例子 Update Pattern III 并将其应用于条形图。

    github 还有一个演示 gh-pages .

    这种模式的阶段是,

    • 更新新数据中的旧元素
    • 输入新数据中的新元素
        2
  •  -1
  •   Oliver Houston    9 年前

    我的绘图函数的第一行是:

    d3.selectAll("svg").remove();
    

    这将在创建新的svg(取决于窗口大小)并使用导入的新数据更新它之前清除svg和所有相关对象。

    您可以单独选择要删除的矩形,但如果轴根据新数据而变化,则只需删除所有内容并再次绘制轴就可能值得了。

    编辑:我认为混淆之处在于“defaultFunction”/“updateFunction”。

     document.getElementById("defaultInput")
      .onclick = defaultFunction;
    document.getElementById("updateInput")
      .onclick = updateFunction;
    defaultFunction();
    

    如果可以分离出图表函数,那么

    function input1() {
    d3.json("data1.json", function(error, data) {
        if (error) {
            return console.error(error);
        } else
     update(data);
    })}
    
     function input2() {
    d3.json("data2.json", function(error, data) {
        if (error) {
            return console.error(error);
        } else
     update(data);
    })}
    
    function update (data){
    remove old data;
    parse new data;
    make graph...
    }
    

    这应该会澄清问题。