D3 refreshing vertical glass bar graph

I have a vertical gigabit chart and want to delete items dynamically rect

. For this, I followed the basic I / O / Update / Logout routine. However, it so happens that the bars seem to be added even if their width is 0;

var drawBars = function(data) {
  var margin = {top: 5, right: 20, bottom: 5, left: 170},
      width = 1020 - margin.left - margin.right,
      height = 1820 - margin.top - margin.bottom,
      scope = this;

  var x = d3.scale.linear()
      .rangeRound([0, width-150]);

  var y = d3.scale.ordinal()
      .rangeBands([0,height], .2, 3);

  var color = d3.scale.category20c();

  var xAxis = d3.svg.axis()
      .scale(x)
      .orient("top")
      .tickSize(0)
      .tickFormat(d3.format("s"));

  var yAxis = d3.svg.axis()
      .scale(y)
      .tickSize(0)
      .orient("left");

  var svg = d3.select('#barchart svg')
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var createData = function(filter) {
    var data = d3.nest()
      .key(function(d) { return d.org; })
      .key(function(d){ return d.taskforce_id })
      .rollup(function(v){ return v.length })
      .entries(scope.rawData['participants']);

      _.each(data, d => {
          _.extend(d, _.object(_.map(d.values, c => {
            if (typeof filter !== 'undefined') {
              if (c.key == filter) {
                return [c.key, c.values];
              }
              return [c.key, 0];
            }
            return [c.key, c.values];
          })));
          delete d.values;
      });

    data.forEach(function(d) {
      var y0 = 0;
      d.orgs = ["A", "B", "C"].map(function(org) {
        if (d[org] === undefined) {
          return {name: org, y0: 0, y1: 0};
        } else {
          return {name: org, y0: y0, y1: y0 += +d[org]};
        }

      });
      d.total = d3.max(d.orgs, d => { return d.y1; });
    });

    data.sort(function(x, y){
       return d3.descending(x.total, y.total);
    });
    return data;
  };

  var redrawChart = function(filter) {
    var data = createData(filter);
    console.log(data);

    x.domain([0, d3.max(data, function(d) { return d.total; })]);
    y.domain(data.map(function(d) { return d.key; }));
    color.domain(d3.keys(data[0]).filter(function(key) { return key !== "key"; }));

    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + 15 + ")")
      .call(xAxis);

    svg.append("g")
      .attr("class", "y axis")
      .call(yAxis)
    .append("text")
      .attr("transform", "rotate(-90)")
      .attr("y", 6)
      .attr("dy", ".71em")
      .style("text-anchor", "end");

    /////////
      //ENTER//
      /////////
    var chartRow = svg.selectAll("g.chartRow")
      .data(data);

    var newRow = chartRow
      .enter()
      .append("g")
      .attr("class", "chartRow")
      .attr("transform", function(d) { return "translate(0, " + y(d.key) + ")"; });

    var rectRow = newRow.selectAll(".bar")
      .data(function(d) { return d.orgs; });

    rectRow
      .enter()
      .append("rect")
      .attr("class", function(d) { return "bar t_"+ d.name; } )
      .attr("height", y.rangeBand())
      .on('click', function(d){
        redrawChart(d.name);
      })
      .style("fill", function(d) { return color(d.name); });

    //////////
      //UPDATE//
      //////////
    chartRow.selectAll('rect').transition()
      .duration(300)
      .attr("width", function(d) { return x(d.y1) - x(d.y0); })
      .attr("x", function(d) { return x(d.y0); })
      .attr("opacity",1);

      ////////
      //EXIT//
      ////////
    chartRow.exit().selectAll("rect.bar").transition()
      .style("opacity","0")
      .attr("transform", "translate(0," + (height + margin.top + margin.bottom) + ")")
      .remove();
  };

  redrawChart();

  var legend = svg.selectAll(".legend")
      .data(color.domain().slice().reverse());

  var legends = legend.enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(0," + i * 25 + ")"; });

  legend.exit().remove();

  legends.append("rect")
      .attr("x", width - 28)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", color);

  legends.append("text")
      .attr("x", width - 34)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) { return d; });

  legends.append("text")
      .attr("x", width + 14)
      .attr("y", 9)
      .attr("class", "numbers")
      .attr("dy", ".35em")
      .style("text-anchor", "end");

};

      

When I console.log

data

look ok, so the filtering works. However, the width of the elements rect

appears to be using the OLD dataset. Equally, legends and axis are duplicated.

The script is here: https://jsfiddle.net/4nm44fgt/

Any ideas?

+3


source to share


1 answer


The second data binding should not only use inbound nodes, as after filtering this selection will be empty:

 var rectRow = chartRow.selectAll(".bar").data(function(d) {
     return d.orgs;
 });

      



instead newRow.selectAll(".bar")...

0


source







All Articles