سؤال

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!

هل كانت مفيدة؟

المحلول

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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top