문제

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