Question

Trying to do a simple replace data/transition with D3 but it's not updating. I'm not getting an error and don't see anything odd when debugging. I feel like i'm missing something super simple and just overlooking. The more eyes, the better!

Here's my D3 code:

var labels = ['Opens', 'Clicks', 'Unsubscribe'],
    data    = [4, 8, 15],
    chart,
    x,
    y,
    gap = 2,
    width = 450,
    leftWidth = 100,
    barHeight = 40,
    barHeightInner = (barHeight / 2),
    barTopMargin = (barHeight - barHeightInner) / 2,
    height = (barHeight + gap * 2) * labels.length + 30;

/*  SET SVG + LEFT MARGIN       */
chart = d3.select($("#graphArea")[0])
    .append('svg')
    .attr('class', 'chart')
    .attr('width', leftWidth + width + 20)
    .attr('height', height)
    .append("g")
    .attr("transform", "translate(10, 20");

x = d3.scale.linear()
    .domain([0, d3.max(data)])
    .range([0, width]);

y = d3.scale.ordinal()
    .domain(data)
    .rangeBands([0, (barHeight + 2 * gap) * labels.length], 0.05);

/* CREATE BARS  */
chart.selectAll("rect")
    .data(data)
    .enter().append("rect")
    .attr("x", leftWidth)
    .attr("y", y)
    .attr("width", x)
    .attr("height", y.rangeBand())
    .attr('class', 'bar-outer');

/* INNER BARS   */
chart.selectAll("rect.inner")
    .data(data)
    .enter().append("rect")
    .attr("x", leftWidth)
    .attr("y", function(d){return y(d) + barTopMargin} )
    .attr("width", function(d){return x(d)/2;})
    .attr("height", barHeightInner)
    .attr('class', 'bar-inner');



 /* SET NAMED LABELS    */
 chart.selectAll("text.label")
  .data(labels)
  .enter().append("text")
  .attr("x", leftWidth / 2 + 40)
.attr("y", function(d,i) {return i * y.rangeBand() + 20;})
  .attr("dy", ".35em")
  .attr("text-anchor", "end")
  .attr('class', 'label')
  .text(String);

function update(data) {

data =  [20, 10, 3];

chart.selectAll("rect")
    .data(data)
    .enter().append("rect")
    .attr("x", leftWidth)
    .attr("y", y)
    .attr("width", x)
    .attr("height", y.rangeBand())
    .attr('class', 'bar-outer');

 chart.selectAll("rect")
    .data(data)
    .exit()
    .transition()
    .duration(300)
    .ease("exp")
    .attr('width', 0)
    .remove();

chart.selectAll("rect")
    .data(data)
    .transition()
    .duration(300)
    .ease("quad")
    .attr("width", x)
    .attr("height", y.rangeBand())
    .attr("transform", function(d,i) { return "translate(" + [0, y(i)] + ")"});

It's kind of messy, sorry... but should be readable at least. I'm not sure why when update(data) it's not changing. Any advice would be greatly appreciated!

Était-ce utile?

La solution

The main problems were with the application of the enter/update/exit pattern and also with forgetting to re-set the scale domains according to the new data. Here is the segment of interest:

function update() {
    data = [20, 10, 3];

    // must re-set scale domains with the new data
    x.domain([0, d3.max(data)]);
    y.domain(data);

    var outer = chart.selectAll(".bar-outer")
        .data(data);

    // exit selection
    outer
        .exit()
        .remove();

    // enter selection
    outer
      .enter()
      .append("rect")
        .attr('class', 'bar-outer');

    // update selection
    outer
        .transition()
        .duration(500)
        .ease("quad")
        .attr("x", leftWidth)
        .attr("y", y)
        .attr("width", x)
        .attr("height", y.rangeBand());

    var inner = chart.selectAll(".bar-inner")
        .data(data);

    // exit selection
    inner
        .exit()
        .remove();

    // enter selection
    inner
      .enter()
      .append("rect")
        .attr('class', 'bar-inner');

    // update selection
    inner
        .transition()
        .duration(500)
        .ease("quad")
        .attr("x", leftWidth)
        .attr("y", function (d) {
            return y(d) + barTopMargin
        })
        .attr("width", function (d) {
            return x(d) / 2;
        })
        .attr("height", barHeightInner);
};

Here is the complete FIDDLE.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top