pieLayout.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  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,
  13. * software distributed under the License is distributed on an
  14. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  15. * KIND, either express or implied. See the License for the
  16. * specific language governing permissions and limitations
  17. * under the License.
  18. */
  19. /**
  20. * AUTO-GENERATED FILE. DO NOT MODIFY.
  21. */
  22. /*
  23. * Licensed to the Apache Software Foundation (ASF) under one
  24. * or more contributor license agreements. See the NOTICE file
  25. * distributed with this work for additional information
  26. * regarding copyright ownership. The ASF licenses this file
  27. * to you under the Apache License, Version 2.0 (the
  28. * "License"); you may not use this file except in compliance
  29. * with the License. You may obtain a copy of the License at
  30. *
  31. * http://www.apache.org/licenses/LICENSE-2.0
  32. *
  33. * Unless required by applicable law or agreed to in writing,
  34. * software distributed under the License is distributed on an
  35. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  36. * KIND, either express or implied. See the License for the
  37. * specific language governing permissions and limitations
  38. * under the License.
  39. */
  40. import { parsePercent, linearMap } from '../../util/number.js';
  41. import * as layout from '../../util/layout.js';
  42. import * as zrUtil from 'zrender/lib/core/util.js';
  43. import { normalizeArcAngles } from 'zrender/lib/core/PathProxy.js';
  44. import { makeInner } from '../../util/model.js';
  45. var PI2 = Math.PI * 2;
  46. var RADIAN = Math.PI / 180;
  47. function getViewRect(seriesModel, api) {
  48. return layout.getLayoutRect(seriesModel.getBoxLayoutParams(), {
  49. width: api.getWidth(),
  50. height: api.getHeight()
  51. });
  52. }
  53. export function getBasicPieLayout(seriesModel, api) {
  54. var viewRect = getViewRect(seriesModel, api);
  55. // center can be string or number when coordinateSystem is specified
  56. var center = seriesModel.get('center');
  57. var radius = seriesModel.get('radius');
  58. if (!zrUtil.isArray(radius)) {
  59. radius = [0, radius];
  60. }
  61. var width = parsePercent(viewRect.width, api.getWidth());
  62. var height = parsePercent(viewRect.height, api.getHeight());
  63. var size = Math.min(width, height);
  64. var r0 = parsePercent(radius[0], size / 2);
  65. var r = parsePercent(radius[1], size / 2);
  66. var cx;
  67. var cy;
  68. var coordSys = seriesModel.coordinateSystem;
  69. if (coordSys) {
  70. // percentage is not allowed when coordinate system is specified
  71. var point = coordSys.dataToPoint(center);
  72. cx = point[0] || 0;
  73. cy = point[1] || 0;
  74. } else {
  75. if (!zrUtil.isArray(center)) {
  76. center = [center, center];
  77. }
  78. cx = parsePercent(center[0], width) + viewRect.x;
  79. cy = parsePercent(center[1], height) + viewRect.y;
  80. }
  81. return {
  82. cx: cx,
  83. cy: cy,
  84. r0: r0,
  85. r: r
  86. };
  87. }
  88. export default function pieLayout(seriesType, ecModel, api) {
  89. ecModel.eachSeriesByType(seriesType, function (seriesModel) {
  90. var data = seriesModel.getData();
  91. var valueDim = data.mapDimension('value');
  92. var viewRect = getViewRect(seriesModel, api);
  93. var _a = getBasicPieLayout(seriesModel, api),
  94. cx = _a.cx,
  95. cy = _a.cy,
  96. r = _a.r,
  97. r0 = _a.r0;
  98. var startAngle = -seriesModel.get('startAngle') * RADIAN;
  99. var endAngle = seriesModel.get('endAngle');
  100. var padAngle = seriesModel.get('padAngle') * RADIAN;
  101. endAngle = endAngle === 'auto' ? startAngle - PI2 : -endAngle * RADIAN;
  102. var minAngle = seriesModel.get('minAngle') * RADIAN;
  103. var minAndPadAngle = minAngle + padAngle;
  104. var validDataCount = 0;
  105. data.each(valueDim, function (value) {
  106. !isNaN(value) && validDataCount++;
  107. });
  108. var sum = data.getSum(valueDim);
  109. // Sum may be 0
  110. var unitRadian = Math.PI / (sum || validDataCount) * 2;
  111. var clockwise = seriesModel.get('clockwise');
  112. var roseType = seriesModel.get('roseType');
  113. var stillShowZeroSum = seriesModel.get('stillShowZeroSum');
  114. // [0...max]
  115. var extent = data.getDataExtent(valueDim);
  116. extent[0] = 0;
  117. var dir = clockwise ? 1 : -1;
  118. var angles = [startAngle, endAngle];
  119. var halfPadAngle = dir * padAngle / 2;
  120. normalizeArcAngles(angles, !clockwise);
  121. startAngle = angles[0], endAngle = angles[1];
  122. var layoutData = getSeriesLayoutData(seriesModel);
  123. layoutData.startAngle = startAngle;
  124. layoutData.endAngle = endAngle;
  125. layoutData.clockwise = clockwise;
  126. var angleRange = Math.abs(endAngle - startAngle);
  127. // In the case some sector angle is smaller than minAngle
  128. var restAngle = angleRange;
  129. var valueSumLargerThanMinAngle = 0;
  130. var currentAngle = startAngle;
  131. data.setLayout({
  132. viewRect: viewRect,
  133. r: r
  134. });
  135. data.each(valueDim, function (value, idx) {
  136. var angle;
  137. if (isNaN(value)) {
  138. data.setItemLayout(idx, {
  139. angle: NaN,
  140. startAngle: NaN,
  141. endAngle: NaN,
  142. clockwise: clockwise,
  143. cx: cx,
  144. cy: cy,
  145. r0: r0,
  146. r: roseType ? NaN : r
  147. });
  148. return;
  149. }
  150. // FIXME 兼容 2.0 但是 roseType 是 area 的时候才是这样?
  151. if (roseType !== 'area') {
  152. angle = sum === 0 && stillShowZeroSum ? unitRadian : value * unitRadian;
  153. } else {
  154. angle = angleRange / validDataCount;
  155. }
  156. if (angle < minAndPadAngle) {
  157. angle = minAndPadAngle;
  158. restAngle -= minAndPadAngle;
  159. } else {
  160. valueSumLargerThanMinAngle += value;
  161. }
  162. var endAngle = currentAngle + dir * angle;
  163. // calculate display angle
  164. var actualStartAngle = 0;
  165. var actualEndAngle = 0;
  166. if (padAngle > angle) {
  167. actualStartAngle = currentAngle + dir * angle / 2;
  168. actualEndAngle = actualStartAngle;
  169. } else {
  170. actualStartAngle = currentAngle + halfPadAngle;
  171. actualEndAngle = endAngle - halfPadAngle;
  172. }
  173. data.setItemLayout(idx, {
  174. angle: angle,
  175. startAngle: actualStartAngle,
  176. endAngle: actualEndAngle,
  177. clockwise: clockwise,
  178. cx: cx,
  179. cy: cy,
  180. r0: r0,
  181. r: roseType ? linearMap(value, extent, [r0, r]) : r
  182. });
  183. currentAngle = endAngle;
  184. });
  185. // Some sector is constrained by minAngle and padAngle
  186. // Rest sectors needs recalculate angle
  187. if (restAngle < PI2 && validDataCount) {
  188. // Average the angle if rest angle is not enough after all angles is
  189. // Constrained by minAngle and padAngle
  190. if (restAngle <= 1e-3) {
  191. var angle_1 = angleRange / validDataCount;
  192. data.each(valueDim, function (value, idx) {
  193. if (!isNaN(value)) {
  194. var layout_1 = data.getItemLayout(idx);
  195. layout_1.angle = angle_1;
  196. var actualStartAngle = 0;
  197. var actualEndAngle = 0;
  198. if (angle_1 < padAngle) {
  199. actualStartAngle = startAngle + dir * (idx + 1 / 2) * angle_1;
  200. actualEndAngle = actualStartAngle;
  201. } else {
  202. actualStartAngle = startAngle + dir * idx * angle_1 + halfPadAngle;
  203. actualEndAngle = startAngle + dir * (idx + 1) * angle_1 - halfPadAngle;
  204. }
  205. layout_1.startAngle = actualStartAngle;
  206. layout_1.endAngle = actualEndAngle;
  207. }
  208. });
  209. } else {
  210. unitRadian = restAngle / valueSumLargerThanMinAngle;
  211. currentAngle = startAngle;
  212. data.each(valueDim, function (value, idx) {
  213. if (!isNaN(value)) {
  214. var layout_2 = data.getItemLayout(idx);
  215. var angle = layout_2.angle === minAndPadAngle ? minAndPadAngle : value * unitRadian;
  216. var actualStartAngle = 0;
  217. var actualEndAngle = 0;
  218. if (angle < padAngle) {
  219. actualStartAngle = currentAngle + dir * angle / 2;
  220. actualEndAngle = actualStartAngle;
  221. } else {
  222. actualStartAngle = currentAngle + halfPadAngle;
  223. actualEndAngle = currentAngle + dir * angle - halfPadAngle;
  224. }
  225. layout_2.startAngle = actualStartAngle;
  226. layout_2.endAngle = actualEndAngle;
  227. currentAngle += dir * angle;
  228. }
  229. });
  230. }
  231. }
  232. });
  233. }
  234. export var getSeriesLayoutData = makeInner();