donut-chart.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  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. var innerRadius = outerRadius * 0.618;
  51. console.log("inner:" + innerRadius + " outer:" + outerRadius);
  52. var arc = d3.svg.arc()
  53. .innerRadius(innerRadius)
  54. .outerRadius(outerRadius);
  55. var cx;
  56. var cy = layout.y1 + 50 + layout.margin + outerRadius;
  57. if (showLabels) {
  58. cx = layout.x1 + layout.margin + outerRadius;
  59. } else {
  60. cx = (layout.x1 + layout.x2) / 2;
  61. }
  62. var pie = d3.layout.pie();
  63. pie.sort(null);
  64. pie.value(function(d) {
  65. var v = d.value;
  66. // make sure it > 0
  67. v = Math.max(v, 1e-6);
  68. return v;
  69. });
  70. //Set up groups
  71. var arcs = g
  72. .selectAll("g.arc")
  73. .data(pie(data))
  74. .enter()
  75. .append("g")
  76. .attr("class", "arc")
  77. .attr("transform", "translate(" + cx + "," + cy + ")");
  78. function tweenPie(finish) {
  79. var start = {
  80. startAngle: 0,
  81. endAngle: 0
  82. };
  83. var i = d3.interpolate(start, finish);
  84. return function(d) {
  85. return arc(i(d));
  86. };
  87. }
  88. //Draw arc paths
  89. var path = arcs.append("path")
  90. .attr("fill", function(d, i) {
  91. if (d.value > 1e-6) {
  92. return this.colors[i];
  93. } else {
  94. return "white";
  95. }
  96. }.bind(this))
  97. .attr("d", arc)
  98. .attr("stroke", function(d, i) {
  99. if (allZero) {
  100. return this.colors[i];
  101. }
  102. }.bind(this))
  103. this.bindTooltip(path);
  104. path.on("click", function (d) {
  105. var data = d.data;
  106. if (data.link) {
  107. this.tooltip.remove();
  108. document.location.href = data.link;
  109. }
  110. }.bind(this))
  111. // Show labels
  112. if (showLabels) {
  113. var lx = layout.x1 + layout.margin + outerRadius * 2 + 30;
  114. var squareW = 15;
  115. var margin = 10;
  116. var select = g.selectAll(".rect")
  117. .data(data)
  118. .enter();
  119. select.append("rect")
  120. .attr("fill", function(d, i) {
  121. return this.colors[i];
  122. }.bind(this))
  123. .attr("x", lx)
  124. .attr("y", function(d, i) {
  125. return layout.y1 + 75 + (squareW + margin) * i + layout.margin;
  126. })
  127. .attr("width", squareW)
  128. .attr("height", squareW);
  129. select.append("text")
  130. .attr("x", lx + squareW + margin)
  131. .attr("y", function(d, i) {
  132. return layout.y1 + 80 + (squareW + margin) * i + layout.margin + squareW / 2;
  133. })
  134. .text(function(d) {
  135. var value = d.value;
  136. if (this.get("type") == "memory") {
  137. value = Converter.memoryToSimpliedUnit(value);
  138. }
  139. return d.label + ' = ' + value + suffix;
  140. }.bind(this));
  141. }
  142. if (middleLabel) {
  143. var highLightColor = this.colors[0];
  144. g.append("text").text(middleLabel).attr("x", cx).attr("y", cy - 10).
  145. attr("class", "donut-highlight-text").attr("fill", highLightColor);
  146. g.append("text").text(middleValue).attr("x", cx).attr("y", cy + 15).
  147. attr("class", "donut-highlight-sub").attr("fill", highLightColor);
  148. }
  149. path.transition()
  150. .duration(500)
  151. .attrTween('d', tweenPie);
  152. },
  153. _dataChange: Ember.observer("data", function() {
  154. this.chart.g.selectAll("*").remove();
  155. if(this.get("data")) {
  156. this.draw();
  157. }
  158. }),
  159. draw: function() {
  160. var colorTargets = this.get("colorTargets");
  161. if (colorTargets) {
  162. var colorTargetReverse = Boolean(this.get("colorTargetReverse"));
  163. var targets = colorTargets.split(" ");
  164. this.colors = ColorUtils.getColors(this.get("data").length, targets, colorTargetReverse);
  165. }
  166. this.renderDonutChart(this.get("data"), this.get("title"), this.get("showLabels"),
  167. this.get("middleLabel"), this.get("middleValue"));
  168. },
  169. didInsertElement: function() {
  170. this.initChart();
  171. this.draw();
  172. },
  173. })