更新模式,退出并删除

时间:2018-09-08 12:13:25

标签: d3.js

我有一个堆叠here。我正在尝试使用D3更新模式创建一个简单的示例。单击更新按钮从数据中随机选择并更新图形。这种情况正在发生,但是它会将新图形放在当前图形之上,而不是删除当前图形。

我正在使用exit() remove(),但显然使用不正确。

2 个答案:

答案 0 :(得分:2)

我认为您的最大问题是,您要在每次更新时创建新的比例尺和轴,而您应该只是通过它们各自的域向比例尺提供更新的数据,然后在每个轴上再次调用它们。

此外,当您在.enter(x,y,宽度和高度属性)上放置新条形图时,您对应该.update的旧条形图没有做任何操作。因此,您还必须放置那些先前存在的条形图(否则条形图看起来会相互重叠)。

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@4.0.0" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script>
</head>

<body>
  <div class="chart-container"></div>
  <button id="btn">Update</button>
  <script>
    var originalData = [{
        "date": "Jan",
        "value": 1507
      },
      {
        "date": "Feb",
        "value": 1600
      },
      {
        "date": "Mar",
        "value": 1281
      },
      {
        "date": "Apr",
        "value": 1898
      },
      {
        "date": "May",
        "value": 1749
      },
      {
        "date": "June",
        "value": 1270
      },
      {
        "date": "July",
        "value": 1712
      },
      {
        "date": "Aug",
        "value": 1270
      },
      {
        "date": "Sept",
        "value": 1257
      },
      {
        "date": "Oct",
        "value": 1257
      },
      {
        "date": "Nov",
        "value": 1277
      },
      {
        "date": "Dec",
        "value": 1057
      }
    ];

    ///////////////////////////// Update function

    function randomizeData(data) {
      var rand = Math.floor(Math.random() * data.length) + 2
      var newData = data.slice(0, rand);
      update(newData)
      console.log(newData)
    }

    ///////////////////////////// Create SVG

    var w = 400;
    var h = 250;

    var margin = {
      top: 20,
      bottom: 40,
      left: 40,
      right: 20
    }

    var width = w - margin.left - margin.right
    var height = h - margin.top - margin.bottom

    var svg = d3.select(".chart-container").append("svg")
      .attr("id", "svg")
      .attr("width", w)
      .attr("height", h)

    var chart = svg.append('g')
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var x = d3.scaleBand()
      .range([0, width])
      .padding(0.1)


    var y = d3.scaleLinear()
      .rangeRound([height, 0])


    var xAxis = chart.append('g')
    var yAxis = chart.append('g')

    ///////////////////////////////// Update function

    function update(graphData) {

      // Recalc domains based on new data
      x.domain(graphData.map(function(d) {
        return d.date
      }));

      y.domain([0, d3.max(graphData, function(d) {
        return d.value;
      })]);

      // Redraw axes based on new data
      xAxis.call(d3.axisBottom(x)).attr("transform", "translate(0," + height + ")")
      yAxis.call(d3.axisLeft(y))

      var u = chart.selectAll(".bar")
        .data(graphData);

      // Enter
      u.enter()
        .append("rect")
        .classed('bar', true)
        .attr('x', function(d) {
          return x(d.date)
        })
        .attr("width", x.bandwidth())
        .attr("y", function(d, i) {
          return y(d.value);
        })
        .attr("height", function(d, i) {
          return height - y(d.value);
        });

      // Update
      u.attr('x', function(d) {
          return x(d.date)
        })
        .attr("width", x.bandwidth())
        .attr("y", function(d, i) {
          return y(d.value);
        })
        .attr("height", function(d, i) {
          return height - y(d.value);
        });

      // Exit
      u.exit()
        .remove();
    }

    randomizeData(originalData);

    var button = document.getElementById('btn');
    button.addEventListener('click', () => randomizeData(originalData));
  </script>
</body>

</html>

stackblitz fork

答案 1 :(得分:1)

只需从更新功能中删除X,Y比例尺和轴,并在更新内使用remove() exit()

///////////////////////////// Update function

function doUpdate(gdata){
    var rand = Math.floor(Math.random()*data.length)+2
    var newData = data.slice(0, rand);
     update(newData)
}

///////////////////////////// Create SVG

var w = 400;
var h = 250;

var margin = {
  top: 20,
  bottom: 40,
  left: 40,
  right: 20
}

var width = w - margin.left - margin.right
var height = h - margin.top - margin.bottom

var svg = d3.select(".chart-container").append("svg")
  .attr("id", "svg")
  .attr("width", w)
  .attr("height", h)

var chart = svg.append('g')
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleBand()
  .range([0, width])
  .padding(0.1)
  .domain(data.map(function(d) { 
    return d.date
  }));

  var y = d3.scaleLinear()
    .rangeRound([height, 0])
    .domain([0, d3.max(data, function(d) { 
      return d.value; 
    })]);

var xAxis = chart.append('g')
    .classed('x-axis', true)
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(x))

  var yAxis = chart.append('g')
    .classed('y-axis', true)
    .call(d3.axisLeft(y))   

///////////////////////////////// Update function

function update(graphData){
  console.log(graphData,graphData.length)
  var u = chart.selectAll(".bar")
    .remove()
    .exit()
    .data(graphData);

    u.enter()
     .append("rect")
     .classed('bar', true)
     .attr('x', function(d){
      return x(d.date)
    })
    .attr("width", x.bandwidth())
    .attr("y", function (d, i) {
      return y(d.value);
    })
    .attr("height", function(d,i){
      return height - y(d.value);
    });



}    
var button = document.getElementById('btn');
button.addEventListener('click', doUpdate);
doUpdate(data);