javascript - d3js display animated text into pie charts -
i have 3 pie charts loaded animation. each of chart, has text inside, percent number, 1 chart loaded follow animation , start counting 0% tot%
i able show text in 1 pie chart, when adapt code used 3 pie charts, cannot find way display 3 text. loop trought 3 div , trhough 3 percent number, can see correct percent number in console, nothing displayed inside pie chart :/
i'm new d3 might easier can see.
app.numbers = { calcperc : function(percent) { return [percent, 100-percent]; }, drawdonutchart : function(el, percent, width, height, text_y) { width = typeof width !== undefined ? width : 290; //width height = typeof height !== undefined ? height : 290; //height text_y = typeof text_y !== undefined ? text_y : "-.10em"; var radius = math.min(width, height) / 2; var pie = d3.pie().sort(null); var dataset = { lower: this.calcperc(0), upper: this.calcperc(percent) } //this.percents = percent; this.arc = d3.arc() .innerradius(radius - 20) .outerradius(radius); var svg = d3.select(el).append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); var path = svg.selectall("path") .data(pie(dataset.lower)) .enter().append("path") .attr("class", function(d, i) { return "color" + }) .attr("d", this.arc) .each(function(d) { this._currentarc = d; }); // store initial values // add text in center of donut this.text = svg.append('text') .attr("text-anchor", "middle") .attr("dy", text_y) .attr("d", percent) if (typeof(percent) === "string") { this.text.text(percent); } else { var self = this; var timeout = settimeout( function () { cleartimeout(timeout); path = path.data(pie(dataset.upper)); // update data path.transition().ease(d3.easeexp).duration('500').attrtween("d", function(a){ var progress = 0; var format = d3.format(".0%"); // store displayed angles in _currentarc. // then, interpolate _currentarc new angles. // during transition, _currentarc updated in-place d3.interpolate. var = d3.interpolate(this._currentarc, a); var i2 = d3.interpolate(progress, percent); this._currentarc = i(0); return function(t) { $(self.text).each(function(){ $(this).text( format(i2(t) / 100) ); }); return self.arc(i(t)); }; }); // redraw arcs }, 200); } }, init : function(){ $('.donut').each( function() { var percent = $(this).data('donut'); app.numbers.drawdonutchart( this, percent, 190, 190, ".35em" ); }) } } } // initialize pie on scroll window.onscroll = function() { app.numbers.init(); } html:
<section class="row numbers section-bkg section-bkg--blue"> <div class="container"> <div class="col-xs-12 col-sm-4"> <div class="donut" data-donut="42"></div> </div> <div class="col-xs-12 col-sm-4"> <div class="donut" data-donut="12"></div> </div> <div class="col-xs-12 col-sm-4"> <div class="donut" data-donut="86"></div> </div> </div> </section> any idea how should display text? i'm pretty sure problem here:
$(self.text).each(function(){ $(this).text( format(i2(t) / 100) ); });
despite mixing jquery , d3 never being idea (try avoid it), seems that not problem. problem seems fact you're changing text inside factory, using assigned self.
one solution (without changing code much, there better ways refactor it) getting texts based on current <path>:
var self2 = this;//this transitioning path return function(t) { d3.select(self2.parentnode).select("text").text(format(i2(t) / 100)); return self.arc(i(t)); }; here code (without jquery):
var app = {}; var color = d3.scaleordinal(d3.schemecategory10) app.numbers = { calcperc: function(percent) { return [percent, 100 - percent]; }, drawdonutchart: function(el, percent, width, height, text_y) { width = typeof width !== undefined ? width : 290; //width height = typeof height !== undefined ? height : 290; //height text_y = typeof text_y !== undefined ? text_y : "-.10em"; var radius = math.min(width, height) / 2; var pie = d3.pie().sort(null); var dataset = { lower: this.calcperc(0), upper: this.calcperc(percent) } //this.percents = percent; this.arc = d3.arc() .innerradius(radius - 20) .outerradius(radius); var svg = d3.select(el).append("svg") .attr("width", width) .attr("height", height) .append("g") .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"); var path = svg.selectall("path") .data(pie(dataset.lower)) .enter().append("path") .attr("fill", function(d, i) { return color(i) }) .attr("d", this.arc) .each(function(d) { this._currentarc = d; }); // store initial values // add text in center of donut this.text = svg.append('text') .attr("text-anchor", "middle") .attr("dy", text_y) .attr("d", percent) this.text.text(percent); var self = this; path = path.data(pie(dataset.upper)); // update data path.transition().ease(d3.easeexp).duration(1000).attrtween("d", function(a) { var progress = 0; var format = d3.format(".0%"); // store displayed angles in _currentarc. // then, interpolate _currentarc new angles. // during transition, _currentarc updated in-place d3.interpolate. var = d3.interpolate(this._currentarc, a); var i2 = d3.interpolate(progress, percent); this._currentarc = i(0); var self2 = this; return function(t) { d3.select(self2.parentnode).select("text").text(format(i2(t) / 100)); return self.arc(i(t)); }; }); // redraw arcs }, init: function() { d3.selectall('.donut').each(function() { var percent = d3.select(this).node().dataset.donut; app.numbers.drawdonutchart( this, percent, 190, 190, ".35em" ); }) } } app.numbers.init(); <script src="https://d3js.org/d3.v4.min.js"></script> <section class="row numbers section-bkg section-bkg--blue"> <div class="container"> <div class="col-xs-12 col-sm-4"> <div class="donut" data-donut="42"></div> </div> <div class="col-xs-12 col-sm-4"> <div class="donut" data-donut="12"></div> </div> <div class="col-xs-12 col-sm-4"> <div class="donut" data-donut="86"></div> </div> </div> </section>
Comments
Post a Comment