Reputation: 542
I try to show multiple donut charts on the same page. But it's not showing. I am using a loop for creating this chart and added multiple html id to show this.
var details = [{category: "Doctor", number: 25}, {category: "Shopping", number: 20}, { category: "Restaurants", number: 10}, { category: "FastFood", number: 5}, { category: "Internet", number: 8},{ category: "Other", number: 32}];
for (i = 1; i <= 4; i++)
chartScript(details, '#custom-chart-' + i);
function chartScript(details, cls) {
var width = 300,
height = 500;
var colors = d3.scaleOrdinal(d3.schemeDark2);
var svg = d3.select(cls).append("svg")
.attr("width", width).attr("height", height);
details.sort(function (a, b) {
return b['number'] - a['number'];
});
var data = d3.pie().sort(null).value(function (d) {
return d.number;
})(details);
var segments = d3.arc()
.innerRadius(80)
.outerRadius(150)
.padAngle(.05)
.padRadius(30);
var sections = svg.append("g").attr("transform", "translate(150,250)").selectAll("path").data(data);
sections.enter().append("path").attr("d", segments).attr("fill", function (d) {
return colors(d.data.number);
});
var content = d3.select("g").selectAll("text").data(data);
content.enter().append("text").classed("inside", true).each(function (d) {
var center = segments.centroid(d);
d3.select(this).attr("x", center[0]).attr("y", center[1]).text(d.data.number + '%')
})
}
I got output like this(1st one is showing % but others are not):
Upvotes: 2
Views: 178
Reputation: 102198
As a rule of thumb: in a D3 code, never use a loop (for
, while
, forEach
etc...) for appending elements.
So, just change that awkward loop for a proper D3 selection...
var cls = d3.select("body").selectAll(null)
.data(d3.range(4))
.enter()
.append("div");
... and not only you will fix the issue you mentioned but also avoid future problems.
Here is a demo using (most of) your code:
var details = [{
category: "Doctor",
number: 25
}, {
category: "Shopping",
number: 20
}, {
category: "Restaurants",
number: 10
}, {
category: "FastFood",
number: 5
}, {
category: "Internet",
number: 8
}, {
category: "Other",
number: 32
}];
var cls = d3.select("body").selectAll(null)
.data(d3.range(4))
.enter()
.append("div");
var width = 180,
height = 180;
var colors = d3.scaleOrdinal(d3.schemeDark2);
var svg = cls.append("svg")
.attr("width", width).attr("height", height);
details.sort(function(a, b) {
return b['number'] - a['number'];
});
var data = d3.pie().sort(null).value(function(d) {
return d.number;
})(details);
var segments = d3.arc()
.innerRadius(45)
.outerRadius(85)
.padAngle(.05)
.padRadius(30);
var g = svg.append("g").attr("transform", "translate(90,90)");
var sections = g.selectAll("path").data(data);
sections.enter().append("path").attr("d", segments).attr("fill", function(d) {
return colors(d.data.number);
});
var content = g.selectAll("text").data(data);
content.enter().append("text").classed("inside", true).each(function(d) {
var center = segments.centroid(d);
d3.select(this).attr("x", center[0]).attr("y", center[1]).text(d.data.number + '%')
})
div {
display: inline-block;
}
text {
text-anchor: middle;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
Upvotes: 1
Reputation: 7954
You are using d3 like this
var sections = svg.append("g").attr("transform", "translate(150,250)")
and in this line
var content = d3.select("g").selectAll("text").data(data);
instead of d3 You should use
var content = sections.select("g").selectAll("text").data(data);
That way it will select all the <g>
tags in the sections
Upvotes: 2