donut-chart.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import Ember from 'ember';
  2. import BaseChartComponent from 'yarn-ui/components/base-chart-component';
  3. export default BaseChartComponent.extend({
  4. /*
  5. * data = [{label="xx", value=},{...}]
  6. */
  7. renderDonutChart: function(data, title, showLabels = false,
  8. middleLabel = "Total", middleValue = undefined) {
  9. var g = this.chart.g;
  10. var layout = this.getLayout();
  11. this.renderTitleAndBG(g, title, layout);
  12. var total = 0;
  13. var allZero = true;
  14. for (var i = 0; i < data.length; i++) {
  15. total += data[i].value;
  16. if (data[i].value > 1e-6) {
  17. allZero = false;
  18. }
  19. }
  20. if (!middleValue) {
  21. middleValue = total;
  22. }
  23. //Width and height
  24. var h = layout.y2 - layout.y1;
  25. // 50 is for title
  26. var outerRadius = (h - 50 - 2 * layout.margin) / 2;
  27. var innerRadius = outerRadius * 0.618;
  28. var arc = d3.svg.arc()
  29. .innerRadius(innerRadius)
  30. .outerRadius(outerRadius);
  31. var cx;
  32. var cy = layout.y1 + 50 + layout.margin + outerRadius;
  33. if (showLabels) {
  34. cx = layout.x1 + layout.margin + outerRadius;
  35. } else {
  36. cx = (layout.x1 + layout.x2) / 2;
  37. }
  38. var pie = d3.layout.pie();
  39. pie.sort(null);
  40. pie.value(function(d) {
  41. var v = d.value;
  42. // make sure it > 0
  43. v = Math.max(v, 1e-6);
  44. return v;
  45. });
  46. //Set up groups
  47. var arcs = g
  48. .selectAll("g.arc")
  49. .data(pie(data))
  50. .enter()
  51. .append("g")
  52. .attr("class", "arc")
  53. .attr("transform", "translate(" + cx + "," + cy + ")");
  54. function tweenPie(finish) {
  55. var start = {
  56. startAngle: 0,
  57. endAngle: 0
  58. };
  59. var i = d3.interpolate(start, finish);
  60. return function(d) {
  61. return arc(i(d));
  62. };
  63. }
  64. //Draw arc paths
  65. var path = arcs.append("path")
  66. .attr("fill", function(d, i) {
  67. if (d.value > 1e-6) {
  68. return this.colors[i];
  69. } else {
  70. return "white";
  71. }
  72. }.bind(this))
  73. .attr("d", arc)
  74. .attr("stroke", function(d, i) {
  75. if (allZero) {
  76. return this.colors[i];
  77. }
  78. }.bind(this))
  79. .attr("stroke-dasharray", function(d, i) {
  80. if (d.value <= 1e-6) {
  81. return "10,10";
  82. }
  83. }.bind(this));
  84. this.bindTooltip(path);
  85. // Show labels
  86. if (showLabels) {
  87. var lx = layout.x1 + layout.margin + outerRadius * 2 + 30;
  88. var squareW = 15;
  89. var margin = 10;
  90. var select = g.selectAll(".rect")
  91. .data(data)
  92. .enter();
  93. select.append("rect")
  94. .attr("fill", function(d, i) {
  95. return this.colors[i];
  96. }.bind(this))
  97. .attr("x", lx)
  98. .attr("y", function(d, i) {
  99. return layout.y1 + 50 + (squareW + margin) * i + layout.margin;
  100. })
  101. .attr("width", squareW)
  102. .attr("height", squareW);
  103. select.append("text")
  104. .attr("x", lx + squareW + margin)
  105. .attr("y", function(d, i) {
  106. return layout.y1 + 50 + (squareW + margin) * i + layout.margin + squareW / 2;
  107. })
  108. .text(function(d) {
  109. return d.label + ' = ' + d.value;
  110. });
  111. }
  112. if (middleLabel) {
  113. var highLightColor = this.colors[0];
  114. g.append("text").text(middleLabel).attr("x", cx).attr("y", cy - 10).
  115. attr("class", "donut-highlight-text").attr("fill", highLightColor);
  116. g.append("text").text(middleValue).attr("x", cx).attr("y", cy + 20).
  117. attr("class", "donut-highlight-text").attr("fill", highLightColor).
  118. style("font-size", "30px");
  119. }
  120. path.transition()
  121. .duration(500)
  122. .attrTween('d', tweenPie);
  123. },
  124. draw: function() {
  125. this.initChart();
  126. this.renderDonutChart(this.get("data"), this.get("title"), this.get("showLabels"),
  127. this.get("middleLabel"), this.get("middleValue"));
  128. },
  129. didInsertElement: function() {
  130. this.draw();
  131. },
  132. })