score:2

Accepted answer

You are missing some pretty important things here. If you are going to do updates on your data you need to do a couple things.

  1. Give a key to the data() function. You need to give D3 a way to identify data when you update it so it knows if it should add, remove, or leave existing data. The key does this. For instance you might do something like this:

    .data(data, function(d) { return d.name })
    

    Now d3 will be able to tell you data items apart assuming d.name is a unique identifier.

  2. You need an exit() for data that is removed during update. You need to save the data joined selection so you can call enter and exit on it:

    var bar = chart.selectAll(".bar")
              .data(data, function(d) { return d.name})
    

    now you can call: bar.exit().remove() to get rid of deleted items and bar.enter() to add items.

  3. You need to make a selection that hasn't had enter() called on it to update attributes.

  4. Probably more a matter of style, but you should set up the SVG and margins outside the update function since they state the same. You can still update the axis and scales by calling the appropriate functions in the update.

The code you posted is a little hard for other people to run — you'll always get better faster answers if you post code that has been reduced to the main problem and that others can run without needing access to offsite data or apis.

Here's an example that updates on a setInterval between two data sets based on your code. But you should also look at the General Update Patterns - they are very simple but have almost everything you need to know. (https://bl.ocks.org/mbostock/3808234)

dataset = [
        {name: "Albert", start: 0, end:220},
        {name: "Mark", start: 0, end:200},
        {name: "Søren", start: 0, end:100},
        {name: "Immanuel", start: 0, end:60},
        {name: "Michel", start: 0, end:90},
        {name: "Jean Paul", start: 0, end: 80}
    ]
     dataset2 = [
        {name: "Albert", start: 0, end:20},
         {name: "Immanuel", start:0, end:220},
        {name: "Jaques", start: 0, end:100},
        {name: "Gerhard", start:0 , end:50},
        {name: "Søren", start: 0, end:150},
        {name: "William", start: 0, end: 180}
    ]

var margin = {
    top: 10,
    right: 30,
    bottom: 30,
    left: 40
  },
  width = 400 - margin.left - margin.right,
  height = 200 - margin.top - margin.bottom,
  padding = 0.3;

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

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

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

chart.append("g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + height + ")")
chart.append("g")
  .attr("class", "y axis")

var currentData = dataset

waterfallChart(currentData)

setInterval(function() {
  currentData = currentData === dataset ? dataset2 : dataset
  waterfallChart(currentData)
}, 3000)

function waterfallChart(data) {
  var t = d3.transition()
    .duration(750)

  x.domain(data.map(function(d) {
    return d.name
  }))
  y.domain([0, d3.max(data, function(d) {
    return d.end
  })])
  var xAxis = d3.axisBottom(x)

  var yAxis = d3.axisLeft(y)

  d3.select('g.x').transition(t).call(xAxis)
  d3.select('g.y').call(yAxis)

  var bar = chart.selectAll(".bar")
    .data(data, function(d) {
      return d.name
    })

  // ENTER -- ADD ITEMS THAT ARE NEW IN DATA
  bar.enter().append("g")
    .attr("transform", function(d) {
      return "translate(" + x(d.name) + ",0)"
    })
    .attr("class", 'bar')
    .append("rect")
    .attr("y", function(d) {
      return y(Math.max(d.start, d.end));
    })
    .attr("height", function(d) {
      return Math.abs(y(d.start) - y(d.end));
    })
    .attr("width", x.bandwidth())

  // UPDATE EXISTING ITEMS
  chart.selectAll(".bar")
    .transition(t)
    .attr("transform", function(d) {
      return "translate(" + x(d.name) + ",0)"
    })
    .select('rect')
    .attr("y", function(d) {
      return y(Math.max(d.start, d.end))
    })
    .attr("height", function(d) {
      return Math.abs(y(d.start) - y(d.end))
    })
    .attr("width", x.bandwidth())

  // REMOVE ITEMS DELETED FROM DATA
  bar.exit().remove()
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg class="chart"></svg>


Related Query