pie_point.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. /**
  2. * DevExtreme (viz/series/points/pie_point.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var extend = require("../../../core/utils/extend").extend;
  11. var symbolPoint = require("./symbol_point");
  12. var _extend = extend;
  13. var _round = Math.round;
  14. var _sqrt = Math.sqrt;
  15. var _acos = Math.acos;
  16. var DEG = 180 / Math.PI;
  17. var _abs = Math.abs;
  18. var vizUtils = require("../../core/utils");
  19. var _normalizeAngle = vizUtils.normalizeAngle;
  20. var _getCosAndSin = vizUtils.getCosAndSin;
  21. var _isDefined = require("../../../core/utils/type").isDefined;
  22. var getVerticallyShiftedAngularCoords = vizUtils.getVerticallyShiftedAngularCoords;
  23. var RADIAL_LABEL_INDENT = require("../../components/consts").radialLabelIndent;
  24. module.exports = _extend({}, symbolPoint, {
  25. _updateData: function(data, argumentChanged) {
  26. var that = this;
  27. symbolPoint._updateData.call(this, data);
  28. if (argumentChanged || !_isDefined(that._visible)) {
  29. that._visible = true
  30. }
  31. that.minValue = that.initialMinValue = that.originalMinValue = _isDefined(data.minValue) ? data.minValue : 0
  32. },
  33. animate: function(complete, duration, delay) {
  34. var that = this;
  35. that.graphic.animate({
  36. x: that.centerX,
  37. y: that.centerY,
  38. outerRadius: that.radiusOuter,
  39. innerRadius: that.radiusInner,
  40. startAngle: that.toAngle,
  41. endAngle: that.fromAngle
  42. }, {
  43. delay: delay,
  44. partitionDuration: duration
  45. }, complete)
  46. },
  47. correctPosition: function(correction) {
  48. var that = this;
  49. that.correctRadius(correction);
  50. that.correctLabelRadius(correction.radiusOuter + RADIAL_LABEL_INDENT);
  51. that.centerX = correction.centerX;
  52. that.centerY = correction.centerY
  53. },
  54. correctRadius: function(correction) {
  55. this.radiusInner = correction.radiusInner;
  56. this.radiusOuter = correction.radiusOuter
  57. },
  58. correctLabelRadius: function(radiusLabels) {
  59. this.radiusLabels = radiusLabels
  60. },
  61. correctValue: function(correction, percent, base) {
  62. var that = this;
  63. that.value = (base || that.normalInitialValue) + correction;
  64. that.minValue = correction;
  65. that.percent = percent;
  66. that._label.setDataField("percent", percent)
  67. },
  68. _updateLabelData: function() {
  69. this._label.setData(this._getLabelFormatObject())
  70. },
  71. _getShiftLabelCoords: function() {
  72. var that = this;
  73. var bBox = that._label.getBoundingRect();
  74. var coord = that._getLabelCoords(that._label);
  75. var visibleArea = that._getVisibleArea();
  76. if (that._isLabelDrawingWithoutPoints) {
  77. return that._checkLabelPosition(coord, bBox, visibleArea)
  78. } else {
  79. return that._getLabelExtraCoord(coord, that._checkVerticalLabelPosition(coord, bBox, visibleArea), bBox)
  80. }
  81. },
  82. _getLabelPosition: function(options) {
  83. return options.position
  84. },
  85. _getLabelCoords: function(label) {
  86. var that = this;
  87. var bBox = label.getBoundingRect();
  88. var options = label.getLayoutOptions();
  89. var angleFunctions = _getCosAndSin(that.middleAngle);
  90. var position = that._getLabelPosition(options);
  91. var radiusInner = that.radiusInner;
  92. var radiusOuter = that.radiusOuter;
  93. var radiusLabels = that.radiusLabels;
  94. var columnsPosition = "columns" === position;
  95. var rad;
  96. var x;
  97. if ("inside" === position) {
  98. rad = radiusInner + (radiusOuter - radiusInner) / 2 + options.radialOffset;
  99. x = that.centerX + rad * angleFunctions.cos - bBox.width / 2
  100. } else {
  101. rad = radiusLabels + options.radialOffset;
  102. if (angleFunctions.cos > .1 || columnsPosition && angleFunctions.cos >= 0) {
  103. x = that.centerX + rad * angleFunctions.cos
  104. } else {
  105. if (angleFunctions.cos < -.1 || columnsPosition && angleFunctions.cos < 0) {
  106. x = that.centerX + rad * angleFunctions.cos - bBox.width
  107. } else {
  108. x = that.centerX + rad * angleFunctions.cos - bBox.width / 2
  109. }
  110. }
  111. }
  112. return {
  113. x: x,
  114. y: _round(that.centerY - rad * angleFunctions.sin - bBox.height / 2)
  115. }
  116. },
  117. _correctLabelCoord: function(coord, moveLabelsFromCenter) {
  118. var that = this;
  119. var label = that._label;
  120. var bBox = label.getBoundingRect();
  121. var labelWidth = bBox.width;
  122. var options = label.getLayoutOptions();
  123. var visibleArea = that._getVisibleArea();
  124. var rightBorderX = visibleArea.maxX - labelWidth;
  125. var leftBorderX = visibleArea.minX;
  126. var angleOfPoint = _normalizeAngle(that.middleAngle);
  127. var centerX = that.centerX;
  128. var connectorOffset = options.connectorOffset;
  129. var x = coord.x;
  130. if ("columns" === options.position) {
  131. if (angleOfPoint <= 90 || angleOfPoint >= 270) {
  132. x = rightBorderX
  133. } else {
  134. x = leftBorderX
  135. }
  136. coord.x = x
  137. } else {
  138. if ("inside" !== options.position && moveLabelsFromCenter) {
  139. if (angleOfPoint <= 90 || angleOfPoint >= 270) {
  140. if (x - connectorOffset < centerX) {
  141. x = centerX + connectorOffset
  142. }
  143. } else {
  144. if (x + labelWidth + connectorOffset > centerX) {
  145. x = centerX - labelWidth - connectorOffset
  146. }
  147. }
  148. coord.x = x
  149. }
  150. }
  151. return coord
  152. },
  153. drawLabel: function() {
  154. this.translate();
  155. this._isLabelDrawingWithoutPoints = true;
  156. this._drawLabel();
  157. this._isLabelDrawingWithoutPoints = false
  158. },
  159. updateLabelCoord: function(moveLabelsFromCenter) {
  160. var that = this;
  161. var bBox = that._label.getBoundingRect();
  162. var coord = that._correctLabelCoord(bBox, moveLabelsFromCenter);
  163. coord = that._checkHorizontalLabelPosition(coord, bBox, that._getVisibleArea());
  164. that._label.shift(_round(coord.x), _round(bBox.y))
  165. },
  166. _checkVerticalLabelPosition: function(coord, box, visibleArea) {
  167. var x = coord.x;
  168. var y = coord.y;
  169. if (coord.y + box.height > visibleArea.maxY) {
  170. y = visibleArea.maxY - box.height
  171. } else {
  172. if (coord.y < visibleArea.minY) {
  173. y = visibleArea.minY
  174. }
  175. }
  176. return {
  177. x: x,
  178. y: y
  179. }
  180. },
  181. _getLabelExtraCoord: function(coord, shiftCoord, box) {
  182. return coord.y !== shiftCoord.y ? getVerticallyShiftedAngularCoords({
  183. x: coord.x,
  184. y: coord.y,
  185. width: box.width,
  186. height: box.height
  187. }, shiftCoord.y - coord.y, {
  188. x: this.centerX,
  189. y: this.centerY
  190. }) : coord
  191. },
  192. _checkHorizontalLabelPosition: function(coord, box, visibleArea) {
  193. var x = coord.x;
  194. var y = coord.y;
  195. if (coord.x + box.width > visibleArea.maxX) {
  196. x = visibleArea.maxX - box.width
  197. } else {
  198. if (coord.x < visibleArea.minX) {
  199. x = visibleArea.minX
  200. }
  201. }
  202. return {
  203. x: x,
  204. y: y
  205. }
  206. },
  207. applyWordWrap: function(moveLabelsFromCenter) {
  208. var that = this;
  209. var label = that._label;
  210. var box = label.getBoundingRect();
  211. var visibleArea = that._getVisibleArea();
  212. var position = label.getLayoutOptions().position;
  213. var width = box.width;
  214. var rowCountChanged = false;
  215. if ("columns" === position && that.series.index > 0) {
  216. width = visibleArea.maxX - that.centerX - that.radiusLabels
  217. } else {
  218. if ("inside" === position) {
  219. if (width > visibleArea.maxX - visibleArea.minX) {
  220. width = visibleArea.maxX - visibleArea.minX
  221. }
  222. } else {
  223. if (moveLabelsFromCenter && box.x < that.centerX && box.width + box.x > that.centerX) {
  224. width = Math.floor((visibleArea.maxX - visibleArea.minX) / 2)
  225. } else {
  226. if (box.x + width > visibleArea.maxX) {
  227. width = visibleArea.maxX - box.x
  228. } else {
  229. if (box.x < visibleArea.minX) {
  230. width = box.x + width - visibleArea.minX
  231. }
  232. }
  233. }
  234. }
  235. }
  236. if (width < box.width) {
  237. rowCountChanged = label.fit(width)
  238. }
  239. return rowCountChanged
  240. },
  241. setLabelTrackerData: function() {
  242. this._label.setTrackerData(this)
  243. },
  244. _checkLabelPosition: function(coord, bBox, visibleArea) {
  245. coord = this._checkHorizontalLabelPosition(coord, bBox, visibleArea);
  246. return this._checkVerticalLabelPosition(coord, bBox, visibleArea)
  247. },
  248. _getLabelConnector: function() {
  249. var that = this;
  250. var rad = that.radiusOuter;
  251. var seriesStyle = that._options.styles.normal;
  252. var strokeWidthBy2 = seriesStyle["stroke-width"] / 2;
  253. var borderWidth = that.series.getOptions().containerBackgroundColor === seriesStyle.stroke ? _round(strokeWidthBy2) : _round(-strokeWidthBy2);
  254. var angleFunctions = _getCosAndSin(_round(that.middleAngle));
  255. return {
  256. x: _round(that.centerX + (rad - borderWidth) * angleFunctions.cos),
  257. y: _round(that.centerY - (rad - borderWidth) * angleFunctions.sin),
  258. angle: that.middleAngle
  259. }
  260. },
  261. _drawMarker: function(renderer, group, animationEnabled, firstDrawing) {
  262. var that = this;
  263. var radiusOuter = that.radiusOuter;
  264. var radiusInner = that.radiusInner;
  265. var fromAngle = that.fromAngle;
  266. var toAngle = that.toAngle;
  267. if (animationEnabled) {
  268. radiusInner = radiusOuter = 0;
  269. if (!firstDrawing) {
  270. fromAngle = toAngle = that.shiftedAngle
  271. }
  272. }
  273. that.graphic = renderer.arc(that.centerX, that.centerY, radiusInner, radiusOuter, toAngle, fromAngle).attr({
  274. "stroke-linejoin": "round"
  275. }).smartAttr(that._getStyle()).data({
  276. "chart-data-point": that
  277. }).sharp().append(group)
  278. },
  279. getTooltipParams: function() {
  280. var that = this;
  281. var angleFunctions = _getCosAndSin(that.middleAngle);
  282. var radiusInner = that.radiusInner;
  283. var radiusOuter = that.radiusOuter;
  284. return {
  285. x: that.centerX + (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.cos,
  286. y: that.centerY - (radiusInner + (radiusOuter - radiusInner) / 2) * angleFunctions.sin,
  287. offset: 0
  288. }
  289. },
  290. _translate: function() {
  291. var that = this;
  292. var angle = that.shiftedAngle || 0;
  293. var value = that.value;
  294. var minValue = that.minValue;
  295. var translator = that._getValTranslator();
  296. that.fromAngle = translator.translate(minValue) + angle;
  297. that.toAngle = translator.translate(value) + angle;
  298. that.middleAngle = translator.translate((value - minValue) / 2 + minValue) + angle;
  299. if (!that.isVisible()) {
  300. that.middleAngle = that.toAngle = that.fromAngle = that.fromAngle || angle
  301. }
  302. },
  303. getMarkerVisibility: function() {
  304. return true
  305. },
  306. _updateMarker: function(animationEnabled, style, _, callback) {
  307. var that = this;
  308. if (!animationEnabled) {
  309. style = _extend({
  310. x: that.centerX,
  311. y: that.centerY,
  312. outerRadius: that.radiusOuter,
  313. innerRadius: that.radiusInner,
  314. startAngle: that.toAngle,
  315. endAngle: that.fromAngle
  316. }, style)
  317. }
  318. that.graphic.smartAttr(style).sharp();
  319. callback && callback()
  320. },
  321. getLegendStyles: function() {
  322. return this._styles.legendStyles
  323. },
  324. isInVisibleArea: function() {
  325. return true
  326. },
  327. hide: function() {
  328. var that = this;
  329. if (that._visible) {
  330. that._visible = false;
  331. that.hideTooltip();
  332. that._options.visibilityChanged()
  333. }
  334. },
  335. show: function() {
  336. var that = this;
  337. if (!that._visible) {
  338. that._visible = true;
  339. that._options.visibilityChanged()
  340. }
  341. },
  342. setInvisibility: function() {
  343. this._label.draw(false)
  344. },
  345. isVisible: function() {
  346. return this._visible
  347. },
  348. _getFormatObject: function(tooltip) {
  349. var formatObject = symbolPoint._getFormatObject.call(this, tooltip);
  350. var percent = this.percent;
  351. formatObject.percent = percent;
  352. formatObject.percentText = tooltip.formatValue(percent, "percent");
  353. return formatObject
  354. },
  355. getColor: function() {
  356. return this._styles.normal.fill
  357. },
  358. coordsIn: function(x, y) {
  359. var that = this;
  360. var lx = x - that.centerX;
  361. var ly = y - that.centerY;
  362. var r = _sqrt(lx * lx + ly * ly);
  363. var fromAngle = that.fromAngle % 360;
  364. var toAngle = that.toAngle % 360;
  365. var angle;
  366. if (r < that.radiusInner || r > that.radiusOuter || 0 === r) {
  367. return false
  368. }
  369. angle = _acos(lx / r) * DEG * (ly > 0 ? -1 : 1);
  370. if (angle < 0) {
  371. angle += 360
  372. }
  373. if (fromAngle === toAngle && _abs(that.toAngle - that.fromAngle) > 1e-4) {
  374. return true
  375. } else {
  376. return fromAngle >= toAngle ? angle <= fromAngle && angle >= toAngle : !(angle >= fromAngle && angle <= toAngle)
  377. }
  378. }
  379. });