javascript - How to add a nice legend to a d3 pie chart -
i have pie chart working ok add nice legend kind of (made in mspaint)
but can't quite make work...
here pie chart code (without legend part) :
<!doctype html> <html> <head> <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script> </head> <body> <script> var newdata = [{ count: 1, emote: "onetwothree" }, { count: 1, emote: "fourfivesix" }, { count: 1, emote: "seveneightnine" }, { count: 15, emote: "teneleventwelve" }, ] // define size & radius of donut pie chart var width = 450, height = 800, radius = math.min(width, height) / 2; // define arc colours var colour = d3.scale.category20(); // define arc ranges var arctext = d3.scale.ordinal() .rangeroundbands([0, width], .1, .3); // determine size of arcs var arc = d3.svg.arc() .innerradius(radius - 130) .outerradius(radius - 10); // create donut pie chart layout var pie = d3.layout.pie() .value(function(d) { return d.count; }) .sort(null); // append svg attributes , append g svg var mysvg = d3.select('body').append("svg") .attr("width", width) .attr("height", height); var svg = mysvg .append("g") .attr("transform", "translate(" + radius + "," + radius + ")"); var svgtext = mysvg .append("g") .attr("transform", "translate(" + radius + "," + radius + ")"); // define inner circle svg.append("circle") .attr("cx", 0) .attr("cy", 0) .attr("r", 100) .attr("fill", "#fff"); // calculate svg paths , fill in colours var g = svg.selectall(".arc") .data(pie(newdata)) .enter().append("g") .attr("class", "arc"); // append path each g g.append("path") .attr("d", arc) //.attr("data-legend", function(d, i){ return parseint(newdata[i].count) + ' ' + newdata[i].emote; }) .attr("fill", function(d, i) { return colour(i); }); var textg = svg.selectall(".labels") .data(pie(newdata)) .enter().append("g") .attr("class", "labels"); // append text labels each arc textg.append("text") .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) .attr("dy", ".35em") .style("text-anchor", "middle") .attr("fill", "#fff") .text(function(d, i) { return d.data.count > 0 ? d.data.emote : ''; }); </script> </body> </html>
i'm surprised there's not more "stock" examples of sort of thing.
here's quickie legend looks nice data:
// again rebind legend var legendg = mysvg.selectall(".legend") // note appending mysvg , not svg make positioning easier .data(pie(newdata)) .enter().append("g") .attr("transform", function(d,i){ return "translate(" + (width - 110) + "," + (i * 15 + 20) + ")"; // place each legend on right , bump each 1 down 15 pixels }) .attr("class", "legend"); legendg.append("rect") // make matching color rect .attr("width", 10) .attr("height", 10) .attr("fill", function(d, i) { return colour(i); }); legendg.append("text") // add text .text(function(d){ return d.value + " " + d.data.emote; }) .style("font-size", 12) .attr("y", 10) .attr("x", 11);
full example:
<!doctype html> <html> <head> <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script> </head> <body> <script> var newdata = [{ count: 1, emote: "onetwothree" }, { count: 1, emote: "fourfivesix" }, { count: 1, emote: "seveneightnine" }, { count: 15, emote: "teneleventwelve" }, ] // define size & radius of donut pie chart var width = 450, height = 800, radius = math.min(width, height) / 2.5; // define arc colours var colour = d3.scale.category20(); // define arc ranges var arctext = d3.scale.ordinal() .rangeroundbands([0, width], .1, .3); // determine size of arcs var arc = d3.svg.arc() .innerradius(radius - 130) .outerradius(radius - 10); // create donut pie chart layout var pie = d3.layout.pie() .value(function(d) { return d.count; }) .sort(null); // append svg attributes , append g svg var mysvg = d3.select('body').append("svg") .attr("width", width) .attr("height", height); var svg = mysvg .append("g") .attr("transform", "translate(" + radius + "," + radius + ")"); var svgtext = mysvg .append("g") .attr("transform", "translate(" + radius + "," + radius + ")"); // define inner circle svg.append("circle") .attr("cx", 0) .attr("cy", 0) .attr("r", 100) .attr("fill", "#fff"); // calculate svg paths , fill in colours var g = svg.selectall(".arc") .data(pie(newdata)) .enter().append("g") .attr("class", "arc"); // append path each g g.append("path") .attr("d", arc) //.attr("data-legend", function(d, i){ return parseint(newdata[i].count) + ' ' + newdata[i].emote; }) .attr("fill", function(d, i) { return colour(i); }); var textg = svg.selectall(".labels") .data(pie(newdata)) .enter().append("g") .attr("class", "labels"); // append text labels each arc textg.append("text") .attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")"; }) .attr("dy", ".35em") .style("text-anchor", "middle") .attr("fill", "#fff") .text(function(d, i) { return d.data.count > 0 ? d.data.emote : ''; }); var legendg = mysvg.selectall(".legend") .data(pie(newdata)) .enter().append("g") .attr("transform", function(d,i){ return "translate(" + (width - 110) + "," + (i * 15 + 20) + ")"; }) .attr("class", "legend"); legendg.append("rect") .attr("width", 10) .attr("height", 10) .attr("fill", function(d, i) { return colour(i); }); legendg.append("text") .text(function(d){ return d.value + " " + d.data.emote; }) .style("font-size", 12) .attr("y", 10) .attr("x", 11); </script> </body> </html>
Comments
Post a Comment