lundi 11 juin 2018

Incorrect transition behavior in diverging stacked bar chart Ember component

Following from this question I have been working with a diverging stack chart written in D3v4. The chart is intended to be used as an ember component.

The chart renders correctly on the initial load but it displays a number of undesirable behaviours when the data refreshes and it transitions to a new set of bars. Such behaviours include:

  • Bars not removing correctly when date goes backwards
  • The furthest right bar being removed when the date goes forwards with the X axis not updating accordingly.

enter image description here

I'm unsure why this occuring. I know that the data being fed to the chart is correct and that the initial render always displays correctly.

The component.js file is split as follows:

didInsertElement() {
    var data = this.get('data')

    var margin = { top: 35, right: 145, bottom: 35, left: 45 };
    var width = 800
    var height = 350

    var svg = 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 + ")");

    this.set("svg", svg)

    var x = scaleBand()
      .rangeRound([0, width])
      .padding(0.1);
    this.set("x", x)
    var y = scaleLinear()
      .rangeRound([height, 0]);
    this.set("y", y)
    var z = scaleOrdinal()
      .range(["steelblue", "darkorange", "red"]);
    this.set("z", z)
    svg.append("g")
      .attr("class", "x-axis axisWhite");

    svg.append("g")
      .attr("class", "y-axis axisWhite");

    this.buildChart()
  },

Then a didUpdateAttrs hook:

didUpdateAttrs() {
    this.buildChart()
  },

Then the function to build the chart:

buildChart() {
    var data = this.get('data')

    var keys = ["count1", "count2", "count3"];

    var series = stack()
      .keys(keys)
      .offset(stackOffsetDiverging)
      (data);

    this.get("x").domain(data.map(d => d.label));

    this.get("y").domain([
      min(series, stackMin),
      max(series, stackMax)
    ]).nice();

    var barGroups = this.get("svg").selectAll("g.layer")
      .data(series);

    barGroups.exit().remove();

    barGroups.enter().insert("g", ".x-axis")
      .classed('layer', true);

    this.get("svg").selectAll("g.layer")
      .attr("fill", d => this.get("z")(d.key));

    var bars = this.get("svg").selectAll("g.layer").selectAll("rect")
      .data(function(d) { return d; });

    bars.exit().remove()
    bars = bars
      .enter()
      .append("rect")
      .attr("width", this.get("x").bandwidth())
      .attr("x", d => this.get("x")(d.data.label))
      .merge(bars)

    bars.transition()
      .attr("y", d => this.get("y")(d[1]))
      .attr("height", d => Math.abs(this.get("y")(d[0])) - this.get("y")(d[1]));

    this.get("svg").selectAll(".x-axis").transition()
      .attr("transform", "translate(0," + this.get("y")(0) + ")")
      .call(axisBottom(this.get("x")));

    this.get("svg").selectAll(".y-axis").transition()
      .call(axisLeft(this.get("y")));

    function stackMin(serie) {
      return min(serie, function(d) { return d[0]; });
    }

    function stackMax(serie) {
      return max(serie, function(d) { return d[1]; });
    }


  }

Unfortunately I haven't been able to get a proper Twiddle up using the ember-d3 module.




Aucun commentaire:

Enregistrer un commentaire