donut-chart.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one
  3. * or more contributor license agreements. See the NOTICE file
  4. * distributed with this work for additional information
  5. * regarding copyright ownership. The ASF licenses this file
  6. * to you under the Apache License, Version 2.0 (the
  7. * "License"); you may not use this file except in compliance
  8. * with the License. You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. import Ember from 'ember';
  19. import BaseChartComponent from 'yarn-ui/components/base-chart-component';
  20. import ColorUtils from 'yarn-ui/utils/color-utils';
  21. import Converter from 'yarn-ui/utils/converter';
  22. export default BaseChartComponent.extend({
  23. /*
  24. * data = [{label="xx", value=},{...}]
  25. */
  26. renderDonutChart: function(data, title, showLabels = false,
  27. middleLabel = "Total", middleValue = undefined, suffix = "") {
  28. var g = this.chart.g;
  29. var layout = this.getLayout();
  30. this.renderTitleAndBG(g, title, layout);
  31. var total = 0;
  32. var allZero = true;
  33. for (var i = 0; i < data.length; i++) {
  34. total += data[i].value;
  35. if (data[i].value > 1e-6) {
  36. allZero = false;
  37. }
  38. }
  39. if (!middleValue) {
  40. if (this.get("type") === "memory") {
  41. middleValue = Converter.memoryToSimpliedUnit(total);
  42. } else {
  43. middleValue = total;
  44. }
  45. }
  46. //Width and height
  47. var h = layout.y2 - layout.y1;
  48. // 50 is for title
  49. var outerRadius = (h - 50 - 2 * layout.margin) / 2;
  50. // Ratio of inner radius to outer radius
  51. var radiusRatio = 0.75;
  52. var innerRadius = outerRadius * radiusRatio;
  53. var arc = d3.svg.arc()
  54. .innerRadius(innerRadius)
  55. .outerRadius(outerRadius);
  56. var cx;
  57. var cy = layout.y1 + 50 + layout.margin + outerRadius;
  58. if (showLabels) {
  59. cx = layout.x1 + layout.margin + outerRadius;
  60. } else {
  61. cx = (layout.x1 + layout.x2) / 2;
  62. }
  63. var pie = d3.layout.pie();
  64. pie.sort(null);
  65. pie.value(function(d) {
  66. var v = d.value;
  67. // make sure it > 0
  68. v = Math.max(v, 1e-6);
  69. return v;
  70. });
  71. //Set up groups
  72. var arcs = g
  73. .selectAll("g.arc")
  74. .data(pie(data))
  75. .enter()
  76. .append("g")
  77. .attr("class", "arc")
  78. .attr("transform", "translate(" + cx + "," + cy + ")");
  79. function tweenPie(finish) {
  80. var start = {
  81. startAngle: 0,
  82. endAngle: 0
  83. };
  84. var i = d3.interpolate(start, finish);
  85. return function(d) {
  86. return arc(i(d));
  87. };
  88. }
  89. //Draw arc paths
  90. var path = arcs.append("path")
  91. .attr("fill", function(d, i) {
  92. if (d.value > 1e-6) {
  93. return this.colors[i];
  94. } else {
  95. return "white";
  96. }
  97. }.bind(this))
  98. .attr("d", arc)
  99. .attr("stroke", function(d, i) {
  100. if (allZero) {
  101. return this.colors[i];
  102. }
  103. }.bind(this));
  104. this.bindTooltip(path);
  105. path.on("click", function (d) {
  106. var data = d.data;
  107. if (data.link) {
  108. this.tooltip.remove();
  109. document.location.href = data.link;
  110. }
  111. }.bind(this));
  112. // Show labels
  113. if (showLabels) {
  114. var lx = layout.x1 + layout.margin + outerRadius * 2 + 30;
  115. var squareW = 15;
  116. var margin = 10;
  117. var select = g.selectAll(".rect")
  118. .data(data)
  119. .enter();
  120. select.append("rect")
  121. .attr("fill", function(d, i) {
  122. return this.colors[i];
  123. }.bind(this))
  124. .attr("x", lx)
  125. .attr("y", function(d, i) {
  126. return layout.y1 + 75 + (squareW + margin) * i + layout.margin;
  127. })
  128. .attr("width", squareW)
  129. .attr("height", squareW);
  130. select.append("text")
  131. .attr("x", lx + squareW + margin)
  132. .attr("y", function(d, i) {
  133. return layout.y1 + 80 + (squareW + margin) * i + layout.margin + squareW / 2;
  134. })
  135. .text(function(d) {
  136. var value = d.value;
  137. if (this.get("type") === "memory") {
  138. value = Converter.memoryToSimpliedUnit(value);
  139. }
  140. return d.label + ' = ' + value + suffix;
  141. }.bind(this));
  142. }
  143. if (middleLabel) {
  144. var highLightColor = this.colors[0];
  145. g.append("text").text(middleLabel).attr("x", cx).attr("y", cy - 10).
  146. attr("class", "donut-highlight-text").attr("fill", highLightColor);
  147. g.append("text").text(middleValue).attr("x", cx).attr("y", cy + 15).
  148. attr("class", "donut-highlight-sub").attr("fill", highLightColor);
  149. }
  150. path.transition()
  151. .duration(500)
  152. .attrTween('d', tweenPie);
  153. },
  154. _dataChange: Ember.observer("data", function() {
  155. this.chart.g.selectAll("*").remove();
  156. if(this.get("data")) {
  157. this.draw();
  158. }
  159. }),
  160. draw: function() {
  161. var colorTargets = this.get("colorTargets");
  162. if (colorTargets) {
  163. var colorTargetReverse = Boolean(this.get("colorTargetReverse"));
  164. var targets = colorTargets.split(" ");
  165. this.colors = ColorUtils.getColors(this.get("data").length, targets, colorTargetReverse);
  166. }
  167. this.renderDonutChart(this.get("data"), this.get("title"), this.get("showLabels"),
  168. this.get("middleLabel"), this.get("middleValue"));
  169. },
  170. didInsertElement: function() {
  171. this.initChart();
  172. this.draw();
  173. },
  174. });