range_symbol_point.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /**
  2. * DevExtreme (viz/series/points/range_symbol_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 each = require("../../../core/utils/iterator").each;
  11. var extend = require("../../../core/utils/extend").extend;
  12. var noop = require("../../../core/utils/common").noop;
  13. var labelModule = require("./label");
  14. var symbolPoint = require("./symbol_point");
  15. var _extend = extend;
  16. var _isDefined = require("../../../core/utils/type").isDefined;
  17. var _math = Math;
  18. var _abs = _math.abs;
  19. var _min = _math.min;
  20. var _max = _math.max;
  21. var _round = _math.round;
  22. var DEFAULT_IMAGE_WIDTH = 20;
  23. var DEFAULT_IMAGE_HEIGHT = 20;
  24. module.exports = _extend({}, symbolPoint, {
  25. deleteLabel: function() {
  26. var that = this;
  27. that._topLabel.dispose();
  28. that._topLabel = null;
  29. that._bottomLabel.dispose();
  30. that._bottomLabel = null
  31. },
  32. hideMarker: function(type) {
  33. var graphic = this.graphic;
  34. var marker = graphic && graphic[type + "Marker"];
  35. var label = this["_" + type + "Label"];
  36. if (marker && "hidden" !== marker.attr("visibility")) {
  37. marker.attr({
  38. visibility: "hidden"
  39. })
  40. }
  41. label.draw(false)
  42. },
  43. setInvisibility: function() {
  44. this.hideMarker("top");
  45. this.hideMarker("bottom")
  46. },
  47. clearVisibility: function() {
  48. var that = this;
  49. var graphic = that.graphic;
  50. var topMarker = graphic && graphic.topMarker;
  51. var bottomMarker = graphic && graphic.bottomMarker;
  52. if (topMarker && topMarker.attr("visibility")) {
  53. topMarker.attr({
  54. visibility: null
  55. })
  56. }
  57. if (bottomMarker && bottomMarker.attr("visibility")) {
  58. bottomMarker.attr({
  59. visibility: null
  60. })
  61. }
  62. },
  63. clearMarker: function() {
  64. var that = this;
  65. var graphic = that.graphic;
  66. var topMarker = graphic && graphic.topMarker;
  67. var bottomMarker = graphic && graphic.bottomMarker;
  68. var emptySettings = that._emptySettings;
  69. topMarker && topMarker.attr(emptySettings);
  70. bottomMarker && bottomMarker.attr(emptySettings)
  71. },
  72. _getLabelPosition: function(markerType) {
  73. var position;
  74. var labelsInside = "inside" === this._options.label.position;
  75. if (!this._options.rotated) {
  76. position = "top" === markerType ^ labelsInside ? "top" : "bottom"
  77. } else {
  78. position = "top" === markerType ^ labelsInside ? "right" : "left"
  79. }
  80. return position
  81. },
  82. _getLabelMinFormatObject: function() {
  83. var that = this;
  84. return {
  85. index: 0,
  86. argument: that.initialArgument,
  87. value: that.initialMinValue,
  88. seriesName: that.series.name,
  89. originalValue: that.originalMinValue,
  90. originalArgument: that.originalArgument,
  91. point: that
  92. }
  93. },
  94. _updateLabelData: function() {
  95. var maxFormatObject = this._getLabelFormatObject();
  96. maxFormatObject.index = 1;
  97. this._topLabel.setData(maxFormatObject);
  98. this._bottomLabel.setData(this._getLabelMinFormatObject())
  99. },
  100. _updateLabelOptions: function() {
  101. var that = this;
  102. var options = this._options.label;
  103. (!that._topLabel || !that._bottomLabel) && that._createLabel();
  104. that._topLabel.setOptions(options);
  105. that._bottomLabel.setOptions(options)
  106. },
  107. _createLabel: function() {
  108. var options = {
  109. renderer: this.series._renderer,
  110. labelsGroup: this.series._labelsGroup,
  111. point: this
  112. };
  113. this._topLabel = new labelModule.Label(options);
  114. this._bottomLabel = new labelModule.Label(options)
  115. },
  116. _getGraphicBBox: function(location) {
  117. var options = this._options;
  118. var images = this._getImage(options.image);
  119. var image = "top" === location ? this._checkImage(images.top) : this._checkImage(images.bottom);
  120. var bBox;
  121. var coord = this._getPositionFromLocation(location);
  122. if (options.visible) {
  123. bBox = image ? this._getImageBBox(coord.x, coord.y) : this._getSymbolBBox(coord.x, coord.y, options.styles.normal.r)
  124. } else {
  125. bBox = {
  126. x: coord.x,
  127. y: coord.y,
  128. width: 0,
  129. height: 0
  130. }
  131. }
  132. return bBox
  133. },
  134. _getPositionFromLocation: function(location) {
  135. var x;
  136. var y;
  137. var isTop = "top" === location;
  138. if (!this._options.rotated) {
  139. x = this.x;
  140. y = isTop ? _min(this.y, this.minY) : _max(this.y, this.minY)
  141. } else {
  142. x = isTop ? _max(this.x, this.minX) : _min(this.x, this.minX);
  143. y = this.y
  144. }
  145. return {
  146. x: x,
  147. y: y
  148. }
  149. },
  150. _checkOverlay: function(bottomCoord, topCoord, topValue) {
  151. return bottomCoord < topCoord + topValue
  152. },
  153. _getOverlayCorrections: function(topCoords, bottomCoords) {
  154. var rotated = this._options.rotated;
  155. var coordSelector = !rotated ? "y" : "x";
  156. var valueSelector = !rotated ? "height" : "width";
  157. var visibleArea = this.series.getValueAxis().getVisibleArea();
  158. var minBound = visibleArea[0];
  159. var maxBound = visibleArea[1];
  160. var delta = _round((topCoords[coordSelector] + topCoords[valueSelector] - bottomCoords[coordSelector]) / 2);
  161. var coord1 = topCoords[coordSelector] - delta;
  162. var coord2 = bottomCoords[coordSelector] + delta;
  163. if (coord1 < minBound) {
  164. delta = minBound - topCoords[coordSelector];
  165. coord1 += delta;
  166. coord2 += delta
  167. } else {
  168. if (coord2 + bottomCoords[valueSelector] > maxBound) {
  169. delta = -(bottomCoords[coordSelector] + bottomCoords[valueSelector] - maxBound);
  170. coord1 += delta;
  171. coord2 += delta
  172. }
  173. }
  174. return {
  175. coord1: coord1,
  176. coord2: coord2
  177. }
  178. },
  179. _checkLabelsOverlay: function(topLocation) {
  180. var that = this;
  181. var topCoords = that._topLabel.getBoundingRect();
  182. var bottomCoords = that._bottomLabel.getBoundingRect();
  183. var corrections = {};
  184. if (!that._options.rotated) {
  185. if ("top" === topLocation) {
  186. if (this._checkOverlay(bottomCoords.y, topCoords.y, topCoords.height)) {
  187. corrections = this._getOverlayCorrections(topCoords, bottomCoords);
  188. that._topLabel.shift(topCoords.x, corrections.coord1);
  189. that._bottomLabel.shift(bottomCoords.x, corrections.coord2)
  190. }
  191. } else {
  192. if (this._checkOverlay(topCoords.y, bottomCoords.y, bottomCoords.height)) {
  193. corrections = this._getOverlayCorrections(bottomCoords, topCoords);
  194. that._topLabel.shift(topCoords.x, corrections.coord2);
  195. that._bottomLabel.shift(bottomCoords.x, corrections.coord1)
  196. }
  197. }
  198. } else {
  199. if ("top" === topLocation) {
  200. if (this._checkOverlay(topCoords.x, bottomCoords.x, bottomCoords.width)) {
  201. corrections = this._getOverlayCorrections(bottomCoords, topCoords);
  202. that._topLabel.shift(corrections.coord2, topCoords.y);
  203. that._bottomLabel.shift(corrections.coord1, bottomCoords.y)
  204. }
  205. } else {
  206. if (this._checkOverlay(bottomCoords.x, topCoords.x, topCoords.width)) {
  207. corrections = this._getOverlayCorrections(topCoords, bottomCoords);
  208. that._topLabel.shift(corrections.coord1, topCoords.y);
  209. that._bottomLabel.shift(corrections.coord2, bottomCoords.y)
  210. }
  211. }
  212. }
  213. },
  214. _drawLabel: function() {
  215. var that = this;
  216. var labels = [];
  217. var notInverted = that._options.rotated ? that.x >= that.minX : that.y < that.minY;
  218. var customVisibility = that._getCustomLabelVisibility();
  219. var topLabel = that._topLabel;
  220. var bottomLabel = that._bottomLabel;
  221. topLabel.pointPosition = notInverted ? "top" : "bottom";
  222. bottomLabel.pointPosition = notInverted ? "bottom" : "top";
  223. if ((that.series.getLabelVisibility() || customVisibility) && that.hasValue() && false !== customVisibility) {
  224. false !== that.visibleTopMarker && labels.push(topLabel);
  225. false !== that.visibleBottomMarker && labels.push(bottomLabel);
  226. each(labels, function(_, label) {
  227. label.draw(true)
  228. });
  229. that._checkLabelsOverlay(that._topLabel.pointPosition)
  230. } else {
  231. topLabel.draw(false);
  232. bottomLabel.draw(false)
  233. }
  234. },
  235. _getImage: function(imageOption) {
  236. var image = {};
  237. if (_isDefined(imageOption)) {
  238. if ("string" === typeof imageOption) {
  239. image.top = image.bottom = imageOption
  240. } else {
  241. image.top = {
  242. url: "string" === typeof imageOption.url ? imageOption.url : imageOption.url && imageOption.url.rangeMaxPoint,
  243. width: "number" === typeof imageOption.width ? imageOption.width : imageOption.width && imageOption.width.rangeMaxPoint,
  244. height: "number" === typeof imageOption.height ? imageOption.height : imageOption.height && imageOption.height.rangeMaxPoint
  245. };
  246. image.bottom = {
  247. url: "string" === typeof imageOption.url ? imageOption.url : imageOption.url && imageOption.url.rangeMinPoint,
  248. width: "number" === typeof imageOption.width ? imageOption.width : imageOption.width && imageOption.width.rangeMinPoint,
  249. height: "number" === typeof imageOption.height ? imageOption.height : imageOption.height && imageOption.height.rangeMinPoint
  250. }
  251. }
  252. }
  253. return image
  254. },
  255. _checkSymbol: function(oldOptions, newOptions) {
  256. var that = this;
  257. var oldSymbol = oldOptions.symbol;
  258. var newSymbol = newOptions.symbol;
  259. var symbolChanged = "circle" === oldSymbol && "circle" !== newSymbol || "circle" !== oldSymbol && "circle" === newSymbol;
  260. var oldImages = that._getImage(oldOptions.image);
  261. var newImages = that._getImage(newOptions.image);
  262. var topImageChanged = that._checkImage(oldImages.top) !== that._checkImage(newImages.top);
  263. var bottomImageChanged = that._checkImage(oldImages.bottom) !== that._checkImage(newImages.bottom);
  264. return symbolChanged || topImageChanged || bottomImageChanged
  265. },
  266. _getSettingsForTwoMarkers: function(style) {
  267. var that = this;
  268. var options = that._options;
  269. var settings = {};
  270. var x = options.rotated ? _min(that.x, that.minX) : that.x;
  271. var y = options.rotated ? that.y : _min(that.y, that.minY);
  272. var radius = style.r;
  273. var points = that._populatePointShape(options.symbol, radius);
  274. settings.top = _extend({
  275. translateX: x + that.width,
  276. translateY: y,
  277. r: radius
  278. }, style);
  279. settings.bottom = _extend({
  280. translateX: x,
  281. translateY: y + that.height,
  282. r: radius
  283. }, style);
  284. if (points) {
  285. settings.top.points = settings.bottom.points = points
  286. }
  287. return settings
  288. },
  289. _hasGraphic: function() {
  290. return this.graphic && this.graphic.topMarker && this.graphic.bottomMarker
  291. },
  292. _drawOneMarker: function(renderer, markerType, imageSettings, settings) {
  293. var that = this;
  294. var graphic = that.graphic;
  295. if (graphic[markerType]) {
  296. that._updateOneMarker(markerType, settings)
  297. } else {
  298. graphic[markerType] = that._createMarker(renderer, graphic, imageSettings, settings)
  299. }
  300. },
  301. _drawMarker: function(renderer, group, animationEnabled, firstDrawing, style) {
  302. var that = this;
  303. var settings = that._getSettingsForTwoMarkers(style || that._getStyle());
  304. var image = that._getImage(that._options.image);
  305. if (that._checkImage(image.top)) {
  306. settings.top = that._getImageSettings(settings.top, image.top)
  307. }
  308. if (that._checkImage(image.bottom)) {
  309. settings.bottom = that._getImageSettings(settings.bottom, image.bottom)
  310. }
  311. that.graphic = that.graphic || renderer.g().append(group);
  312. that.visibleTopMarker && that._drawOneMarker(renderer, "topMarker", image.top, settings.top);
  313. that.visibleBottomMarker && that._drawOneMarker(renderer, "bottomMarker", image.bottom, settings.bottom)
  314. },
  315. _getSettingsForTracker: function(radius) {
  316. var that = this;
  317. var rotated = that._options.rotated;
  318. return {
  319. translateX: rotated ? _min(that.x, that.minX) - radius : that.x - radius,
  320. translateY: rotated ? that.y - radius : _min(that.y, that.minY) - radius,
  321. width: that.width + 2 * radius,
  322. height: that.height + 2 * radius
  323. }
  324. },
  325. isInVisibleArea: function() {
  326. var that = this;
  327. var rotated = that._options.rotated;
  328. var argument = !rotated ? that.x : that.y;
  329. var maxValue = !rotated ? _max(that.minY, that.y) : _max(that.minX, that.x);
  330. var minValue = !rotated ? _min(that.minY, that.y) : _min(that.minX, that.x);
  331. var tmp;
  332. var visibleTopMarker = true;
  333. var visibleBottomMarker = true;
  334. var visibleRangeArea = true;
  335. var visibleArgArea = that.series.getArgumentAxis().getVisibleArea();
  336. var visibleValArea = that.series.getValueAxis().getVisibleArea();
  337. var notVisibleByArg = visibleArgArea[1] < argument || visibleArgArea[0] > argument;
  338. var notVisibleByVal = visibleValArea[0] > minValue && visibleValArea[0] > maxValue || visibleValArea[1] < minValue && visibleValArea[1] < maxValue;
  339. if (notVisibleByArg || notVisibleByVal) {
  340. visibleTopMarker = visibleBottomMarker = visibleRangeArea = false
  341. } else {
  342. visibleTopMarker = visibleValArea[0] <= minValue && visibleValArea[1] > minValue;
  343. visibleBottomMarker = visibleValArea[0] < maxValue && visibleValArea[1] >= maxValue;
  344. if (rotated) {
  345. tmp = visibleTopMarker;
  346. visibleTopMarker = visibleBottomMarker;
  347. visibleBottomMarker = tmp
  348. }
  349. }
  350. that.visibleTopMarker = visibleTopMarker;
  351. that.visibleBottomMarker = visibleBottomMarker;
  352. return visibleRangeArea
  353. },
  354. getTooltipParams: function() {
  355. var that = this;
  356. var x;
  357. var y;
  358. var rotated = that._options.rotated;
  359. var minValue = !rotated ? _min(that.y, that.minY) : _min(that.x, that.minX);
  360. var side = !rotated ? "height" : "width";
  361. var visibleArea = that._getVisibleArea();
  362. var minVisible = rotated ? visibleArea.minX : visibleArea.minY;
  363. var maxVisible = rotated ? visibleArea.maxX : visibleArea.maxY;
  364. var min = _max(minVisible, minValue);
  365. var max = _min(maxVisible, minValue + that[side]);
  366. if (!rotated) {
  367. x = that.x;
  368. y = min + (max - min) / 2
  369. } else {
  370. y = that.y;
  371. x = min + (max - min) / 2
  372. }
  373. return {
  374. x: x,
  375. y: y,
  376. offset: 0
  377. }
  378. },
  379. _translate: function() {
  380. var that = this;
  381. var rotated = that._options.rotated;
  382. symbolPoint._translate.call(that);
  383. that.height = rotated ? 0 : _abs(that.minY - that.y);
  384. that.width = rotated ? _abs(that.x - that.minX) : 0
  385. },
  386. hasCoords: function() {
  387. return symbolPoint.hasCoords.call(this) && !(null === this.minX || null === this.minY)
  388. },
  389. _updateData: function(data) {
  390. var that = this;
  391. symbolPoint._updateData.call(that, data);
  392. that.minValue = that.initialMinValue = that.originalMinValue = data.minValue
  393. },
  394. _getImageSettings: function(settings, image) {
  395. return {
  396. href: image.url || image.toString(),
  397. width: image.width || DEFAULT_IMAGE_WIDTH,
  398. height: image.height || DEFAULT_IMAGE_HEIGHT,
  399. translateX: settings.translateX,
  400. translateY: settings.translateY
  401. }
  402. },
  403. getCrosshairData: function(x, y) {
  404. var that = this;
  405. var rotated = that._options.rotated;
  406. var minX = that.minX;
  407. var minY = that.minY;
  408. var vx = that.vx;
  409. var vy = that.vy;
  410. var value = that.value;
  411. var minValue = that.minValue;
  412. var argument = that.argument;
  413. var coords = {
  414. axis: that.series.axis,
  415. x: vx,
  416. y: vy,
  417. yValue: value,
  418. xValue: argument
  419. };
  420. if (rotated) {
  421. coords.yValue = argument;
  422. if (_abs(vx - x) < _abs(minX - x)) {
  423. coords.xValue = value
  424. } else {
  425. coords.x = minX;
  426. coords.xValue = minValue
  427. }
  428. } else {
  429. if (_abs(vy - y) >= _abs(minY - y)) {
  430. coords.y = minY;
  431. coords.yValue = minValue
  432. }
  433. }
  434. return coords
  435. },
  436. _updateOneMarker: function(markerType, settings) {
  437. this.graphic && this.graphic[markerType] && this.graphic[markerType].attr(settings)
  438. },
  439. _updateMarker: function(animationEnabled, style) {
  440. this._drawMarker(void 0, void 0, false, false, style)
  441. },
  442. _getFormatObject: function(tooltip) {
  443. var that = this;
  444. var initialMinValue = that.initialMinValue;
  445. var initialValue = that.initialValue;
  446. var initialArgument = that.initialArgument;
  447. var minValue = tooltip.formatValue(initialMinValue);
  448. var value = tooltip.formatValue(initialValue);
  449. return {
  450. argument: initialArgument,
  451. argumentText: tooltip.formatValue(initialArgument, "argument"),
  452. valueText: minValue + " - " + value,
  453. rangeValue1Text: minValue,
  454. rangeValue2Text: value,
  455. rangeValue1: initialMinValue,
  456. rangeValue2: initialValue,
  457. seriesName: that.series.name,
  458. point: that,
  459. originalMinValue: that.originalMinValue,
  460. originalValue: that.originalValue,
  461. originalArgument: that.originalArgument
  462. }
  463. },
  464. getLabel: function() {
  465. return [this._topLabel, this._bottomLabel]
  466. },
  467. getLabels: function() {
  468. return [this._topLabel, this._bottomLabel]
  469. },
  470. getBoundingRect: noop,
  471. coordsIn: function(x, y) {
  472. var trackerRadius = this._storeTrackerR();
  473. var xCond = x >= this.x - trackerRadius && x <= this.x + trackerRadius;
  474. var yCond = y >= this.y - trackerRadius && y <= this.y + trackerRadius;
  475. if (this._options.rotated) {
  476. return yCond && (xCond || x >= this.minX - trackerRadius && x <= this.minX + trackerRadius)
  477. } else {
  478. return xCond && (yCond || y >= this.minY - trackerRadius && y <= this.minY + trackerRadius)
  479. }
  480. },
  481. getMaxValue: function() {
  482. if ("discrete" !== this.series.valueAxisType) {
  483. return this.minValue > this.value ? this.minValue : this.value
  484. }
  485. return this.value
  486. },
  487. getMinValue: function() {
  488. if ("discrete" !== this.series.valueAxisType) {
  489. return this.minValue < this.value ? this.minValue : this.value
  490. }
  491. return this.minValue
  492. }
  493. });