jeudi 25 janvier 2018

Adding a smooth transition to d3 pie chart in Ember

I have a D3 pie chart that does almost everything I want it to do. It refreshes when the data changes and renders correctly.

I am having trouble adding a transition to the initial render and to the re-render when the data changes. I'd like to add a similar animation to the one visible here that was offered as a response to this question but I only receive 'Error: attribute d: Expected moveto path command ('M' or 'm') in the console when I try.

I tried to create a twiddle but couldn't get it to represent correctly. Full code for the component is here:

export default Component.extend({

  didInsertElement() {

    this.pieChart();
  },

  didUpdateAttrs() {
    this.pieChart();
  },
  pieChart() {
    let data = this.get('data');
    let div = select('body')
      .append("div")
      .attr("class", "tooltip"),
      width = 500,
      height = 500,
      donutwidth = 75,
      radius = Math.min(width, height) / 2,
      marc = arc().outerRadius(radius - 10).innerRadius(0),
      labelArc = arc().outerRadius(radius - 40)
      .innerRadius(radius - 40),
      color = scaleOrdinal(schemeCategory10),
      mpie = pie()
      .value((d) => {
        return d.count;
      })(data),

      svg = select(this.$('svg')[0])
      .append("g")
      .attr("transform", "translate(" + width / 2 + ", " +
        height / 2 + ")");

    let gUpdate = svg.selectAll("arc").data(mpie).exit().remove();

    let gEnter = svg.selectAll("arc")
      .data(mpie)
      .enter().append("g")
      .merge(gUpdate)
      .attr("class", "arc")

    //events
    gEnter
      .on("mousemove", function(d) {
        var mouseVal = mouse(this);
        div
          .html("Minutes: " + d.data.count + "</br>" + "Date: " + d.data.label)
          .style("left", (event.pageX + 12) + "px")
          .style("top", (event.pageY - 10) + "px")
          .style("opacity", 1)
          .style("display", "block");
      })
      .on("mouseout", function() {
        div.html(" ").style("display", "none");
      })
      .on('click', d => {
        let clickedLabel = d.data.label;
        let clickedCount = d.data.count;

        if (this.get('on-click')) {
          this.get('on-click')(clickedLabel)
        } else {
          if (clickedLabel === this.get('selectedLabel')) {
            this.set('selectedLabel', '');
            this.set('selectedCount', '');
          } else {
            this.set('selectedLabel', clickedLabel);
            this.set('selectedCount', clickedCount);
          }
        }
      })

    //path
    gEnter.append("path")
      .attr("d", marc)
      .attr("fill", (d, i) => {
        return color(i);
      })

    //Labels
    gEnter.append("text")
      .attr("transform", (d) => {
        return "translate(" +
          labelArc.centroid(d) + ")";
      })
      .text((d) => {
        return d.data.label;
      })
      .attr("text-anchor", "middle")
      .style("fill", "#FFF")
      .each((d) => {
        this.set('chartContextLable', d);
      })
  }
});

As I do not have a var path = declaration I tried to add the transition code in the gEnter.append("path") as follows:

 //path
    gEnter.append("path")
      .attr("d", marc)
      .attr("fill", (d, i) => {
        return color(i);
      })
      .transition()
   .duration(function(d, i) {
     return i * 800;
   })
   .attrTween('d', function(d) {
  var i = interpolate(d.startAngle+0.1, d.endAngle);
  return function(t) {
      d.endAngle = i(t);
    return arc(d);
  }
});

Then I receive the errors. Note that I am using ember-d3 to load the d3 modules which is why they don't have d3 namepaces.




Aucun commentaire:

Enregistrer un commentaire