Pie.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /* *
  2. * (c) 2010-2019 Torstein Honsi
  3. *
  4. * 3D pie series
  5. *
  6. * License: www.highcharts.com/license
  7. */
  8. 'use strict';
  9. import H from '../parts/Globals.js';
  10. import '../parts/Utilities.js';
  11. var deg2rad = H.deg2rad,
  12. pick = H.pick,
  13. seriesTypes = H.seriesTypes,
  14. svg = H.svg,
  15. wrap = H.wrap;
  16. /**
  17. * The thickness of a 3D pie. Requires `highcharts-3d.js`
  18. *
  19. * @type {number}
  20. * @default 0
  21. * @since 4.0
  22. * @product highcharts
  23. * @apioption plotOptions.pie.depth
  24. */
  25. wrap(seriesTypes.pie.prototype, 'translate', function (proceed) {
  26. proceed.apply(this, [].slice.call(arguments, 1));
  27. // Do not do this if the chart is not 3D
  28. if (!this.chart.is3d()) {
  29. return;
  30. }
  31. var series = this,
  32. seriesOptions = series.options,
  33. depth = seriesOptions.depth || 0,
  34. options3d = series.chart.options.chart.options3d,
  35. alpha = options3d.alpha,
  36. beta = options3d.beta,
  37. z = seriesOptions.stacking ?
  38. (seriesOptions.stack || 0) * depth :
  39. series._i * depth;
  40. z += depth / 2;
  41. if (seriesOptions.grouping !== false) {
  42. z = 0;
  43. }
  44. series.data.forEach(function (point) {
  45. var shapeArgs = point.shapeArgs,
  46. angle;
  47. point.shapeType = 'arc3d';
  48. shapeArgs.z = z;
  49. shapeArgs.depth = depth * 0.75;
  50. shapeArgs.alpha = alpha;
  51. shapeArgs.beta = beta;
  52. shapeArgs.center = series.center;
  53. angle = (shapeArgs.end + shapeArgs.start) / 2;
  54. point.slicedTranslation = {
  55. translateX: Math.round(
  56. Math.cos(angle) *
  57. seriesOptions.slicedOffset *
  58. Math.cos(alpha * deg2rad)
  59. ),
  60. translateY: Math.round(
  61. Math.sin(angle) *
  62. seriesOptions.slicedOffset *
  63. Math.cos(alpha * deg2rad)
  64. )
  65. };
  66. });
  67. });
  68. wrap(
  69. seriesTypes.pie.prototype.pointClass.prototype,
  70. 'haloPath',
  71. function (proceed) {
  72. var args = arguments;
  73. return this.series.chart.is3d() ? [] : proceed.call(this, args[1]);
  74. }
  75. );
  76. wrap(
  77. seriesTypes.pie.prototype,
  78. 'pointAttribs',
  79. function (proceed, point, state) {
  80. var attr = proceed.call(this, point, state),
  81. options = this.options;
  82. if (this.chart.is3d() && !this.chart.styledMode) {
  83. attr.stroke = options.edgeColor || point.color || this.color;
  84. attr['stroke-width'] = pick(options.edgeWidth, 1);
  85. }
  86. return attr;
  87. }
  88. );
  89. wrap(seriesTypes.pie.prototype, 'drawDataLabels', function (proceed) {
  90. if (this.chart.is3d()) {
  91. var series = this,
  92. chart = series.chart,
  93. options3d = chart.options.chart.options3d;
  94. series.data.forEach(function (point) {
  95. var shapeArgs = point.shapeArgs,
  96. r = shapeArgs.r,
  97. // #3240 issue with datalabels for 0 and null values
  98. a1 = (shapeArgs.alpha || options3d.alpha) * deg2rad,
  99. b1 = (shapeArgs.beta || options3d.beta) * deg2rad,
  100. a2 = (shapeArgs.start + shapeArgs.end) / 2,
  101. labelPosition = point.labelPosition,
  102. connectorPosition = labelPosition.connectorPosition,
  103. yOffset = (-r * (1 - Math.cos(a1)) * Math.sin(a2)),
  104. xOffset = r * (Math.cos(b1) - 1) * Math.cos(a2);
  105. // Apply perspective on label positions
  106. [
  107. labelPosition.natural,
  108. connectorPosition.breakAt,
  109. connectorPosition.touchingSliceAt
  110. ].forEach(function (coordinates) {
  111. coordinates.x += xOffset;
  112. coordinates.y += yOffset;
  113. });
  114. });
  115. }
  116. proceed.apply(this, [].slice.call(arguments, 1));
  117. });
  118. wrap(seriesTypes.pie.prototype, 'addPoint', function (proceed) {
  119. proceed.apply(this, [].slice.call(arguments, 1));
  120. if (this.chart.is3d()) {
  121. // destroy (and rebuild) everything!!!
  122. this.update(this.userOptions, true); // #3845 pass the old options
  123. }
  124. });
  125. wrap(seriesTypes.pie.prototype, 'animate', function (proceed) {
  126. if (!this.chart.is3d()) {
  127. proceed.apply(this, [].slice.call(arguments, 1));
  128. } else {
  129. var args = arguments,
  130. init = args[1],
  131. animation = this.options.animation,
  132. attribs,
  133. center = this.center,
  134. group = this.group,
  135. markerGroup = this.markerGroup;
  136. if (svg) { // VML is too slow anyway
  137. if (animation === true) {
  138. animation = {};
  139. }
  140. // Initialize the animation
  141. if (init) {
  142. // Scale down the group and place it in the center
  143. group.oldtranslateX = group.translateX;
  144. group.oldtranslateY = group.translateY;
  145. attribs = {
  146. translateX: center[0],
  147. translateY: center[1],
  148. scaleX: 0.001, // #1499
  149. scaleY: 0.001
  150. };
  151. group.attr(attribs);
  152. if (markerGroup) {
  153. markerGroup.attrSetters = group.attrSetters;
  154. markerGroup.attr(attribs);
  155. }
  156. // Run the animation
  157. } else {
  158. attribs = {
  159. translateX: group.oldtranslateX,
  160. translateY: group.oldtranslateY,
  161. scaleX: 1,
  162. scaleY: 1
  163. };
  164. group.animate(attribs, animation);
  165. if (markerGroup) {
  166. markerGroup.animate(attribs, animation);
  167. }
  168. // Delete this function to allow it only once
  169. this.animate = null;
  170. }
  171. }
  172. }
  173. });