D3 Data Refresh Overlay second graph instead of refresh

I'm new to D3 and working on a multiple histogram that can be sent with new data and it will update the existing graph based on the new data it receives.

It currently draws the chart correctly, but when the data changes, it overlays the new data plot on top of the old plot instead of updating it.

I believe the problem must be with my variable bars

and how I bind my data, but I cannot be sure. The data is just a reddit post estimate from the reddit JSON API.

Example: Graph problem

My code for the diagram:

d3.namespace.barChart = function() {
var data, group, height, margin = {top: 0, right: 0, bottom: 0, left: 0}, width;

function chart(container) {
  group = container;
  // Determine the max score and timestamps from the Reddit data for use in our scales
  var maxScore = d3.max(data, function(d) { return d.data.score; });
  data.forEach(function(d) {
    d.data.created *= 1000;
  });

  // Create the scales to ensure data fits in the graphs
  var xScale = d3.scale.ordinal()
    .domain(d3.range(data.length))
    .rangeBands([0, width], 0.25);

  var yScale = d3.scale.linear()
    .domain([0, maxScore])
    .range([0, height]); // .range(starting, )

  var yScaleLine = d3.scale.linear()
    .domain([0, maxScore])
    .range([height, 0]);

  var colorScale = d3.scale.linear()
    .domain(d3.extent(data, function(d) { return d.data.score; }))
    .range(['#DA4453', '#A0D468'])
    .interpolate(d3.interpolateRgb);


  // Create the Y-Axis function. yScaleLine is used as the scale to ensure
  // that the data goes from 0 at the bottom left to max score in the top left
  var yAxis = d3.svg.axis()
    .scale(yScaleLine)
    .orient('left');

  // Setup our chart using our width, height and margins.
  group.attr('width', width + margin.left + margin.right)
    .attr('height', height + margin.top + margin.bottom);

  // Add a group element for the primary graphic that is moved
  // using the margins. Left and top are used since 0,0 is top left corner
  var graph = group.append('g')
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  // Append our yAxis to the SVG canvas and move it according to the margins
  group.append('g')
    .attr('class', 'y axis')
    .call(yAxis)
    .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

  // Inside of our group, we need to make a 'rect' for each item in the dataset
  // We link the data, and append one rect for each piece of data.
  var bars = graph.selectAll('rect')
    .data(data, function(d) { return d.data.id; });

  bars.enter()
    .append('rect');
    // We begin with the height of each bar as 0 allowing us to transition to their full height
  bars.attr({
      x: function(d, i) { return xScale(i); },
      y: function() { return height; },
      height: 0,
      width: xScale.rangeBand(),
      fill:  function(d) { return colorScale(d.data.score); }
    });


    // Events must be linked before a transition to function
    bars.on('mouseover', function() {
      d3.select(this).attr('fill', '#000');
    })
    .on('mouseleave', function() {
      d3.select(this).attr('fill', function(d) { return colorScale(d.data.score); });
    });


    bars.transition().duration(150)
    .attr({
      x: function(d, i) { return xScale(i); },
      y: function(d) { return height - yScale(d.data.score); },
      height: function(d) { return yScale(d.data.score); },
      width: xScale.rangeBand()
    });

  bars.exit().transition().duration(150).attr({ height: 0.0001 }).remove();
}

      

EDIT: After digging into the generated source, it seems like it is not updating, but just keeps creating a new svg element g

for all rect

s. Deleting the chain group.append('g')

fixes the graph, which is not updating, but the graph is no longer in the group and makes the SVG very messy. Source Code Problem

+3


source to share





All Articles