base_indicators.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /**
  2. * DevExtreme (viz/gauges/base_indicators.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 noop = require("../../core/utils/common").noop;
  11. var each = require("../../core/utils/iterator").each;
  12. var _isFinite = isFinite;
  13. var _Number = Number;
  14. var _round = Math.round;
  15. var baseGaugeModule = require("./base_gauge");
  16. var _formatValue = baseGaugeModule.formatValue;
  17. var _getSampleText = baseGaugeModule.getSampleText;
  18. var _patchFontOptions = require("../core/utils").patchFontOptions;
  19. var extend = require("../../core/utils/extend").extend;
  20. var Class = require("../../core/class");
  21. var BaseElement = Class.inherit({
  22. ctor: function(parameters) {
  23. var that = this;
  24. each(parameters, function(name, value) {
  25. that["_" + name] = value
  26. });
  27. that._init()
  28. },
  29. dispose: function() {
  30. var that = this;
  31. that._dispose();
  32. each(that, function(name) {
  33. that[name] = null
  34. });
  35. return that
  36. },
  37. getOffset: function() {
  38. return _Number(this._options.offset) || 0
  39. }
  40. });
  41. var BaseIndicator = BaseElement.inherit({
  42. _init: function() {
  43. var that = this;
  44. that._rootElement = that._createRoot().linkOn(that._owner, {
  45. name: "value-indicator",
  46. after: "core"
  47. });
  48. that._trackerElement = that._createTracker()
  49. },
  50. _dispose: function() {
  51. this._rootElement.linkOff()
  52. },
  53. _setupAnimation: function() {
  54. var that = this;
  55. if (that._options.animation) {
  56. that._animation = {
  57. step: function(pos) {
  58. that._actualValue = that._animation.start + that._animation.delta * pos;
  59. that._actualPosition = that._translator.translate(that._actualValue);
  60. that._move()
  61. },
  62. duration: that._options.animation.duration > 0 ? _Number(that._options.animation.duration) : 0,
  63. easing: that._options.animation.easing
  64. }
  65. }
  66. },
  67. _runAnimation: function(value) {
  68. var that = this;
  69. var animation = that._animation;
  70. animation.start = that._actualValue;
  71. animation.delta = value - that._actualValue;
  72. that._rootElement.animate({
  73. _: 0
  74. }, {
  75. step: animation.step,
  76. duration: animation.duration,
  77. easing: animation.easing
  78. })
  79. },
  80. _createRoot: function() {
  81. return this._renderer.g().attr({
  82. "class": this._className
  83. })
  84. },
  85. _createTracker: function() {
  86. return this._renderer.path([], "area")
  87. },
  88. _getTrackerSettings: noop,
  89. clean: function() {
  90. var that = this;
  91. that._animation && that._rootElement.stopAnimation();
  92. that._rootElement.linkRemove().clear();
  93. that._clear();
  94. that._tracker.detach(that._trackerElement);
  95. that._options = that.enabled = that._animation = null;
  96. return that
  97. },
  98. render: function(options) {
  99. var that = this;
  100. that.type = options.type;
  101. that._options = options;
  102. that._actualValue = that._currentValue = that._translator.adjust(that._options.currentValue);
  103. that.enabled = that._isEnabled();
  104. if (that.enabled) {
  105. that._setupAnimation();
  106. that._rootElement.attr({
  107. fill: that._options.color
  108. }).linkAppend();
  109. that._tracker.attach(that._trackerElement, that, that._trackerInfo)
  110. }
  111. return that
  112. },
  113. resize: function(layout) {
  114. var that = this;
  115. that._rootElement.clear();
  116. that._clear();
  117. that.visible = that._isVisible(layout);
  118. if (that.visible) {
  119. extend(that._options, layout);
  120. that._actualPosition = that._translator.translate(that._actualValue);
  121. that._render();
  122. that._trackerElement.attr(that._getTrackerSettings());
  123. that._move()
  124. }
  125. return that
  126. },
  127. value: function(arg, _noAnimation) {
  128. var that = this;
  129. var val;
  130. var rootElement = this._rootElement;
  131. var visibility = null;
  132. if (void 0 === arg) {
  133. return that._currentValue
  134. }
  135. if (null === arg) {
  136. visibility = "hidden";
  137. that._currentValue = arg
  138. } else {
  139. val = that._translator.adjust(arg);
  140. if (that._currentValue !== val && _isFinite(val)) {
  141. that._currentValue = val;
  142. if (that.visible) {
  143. if (that._animation && !_noAnimation) {
  144. that._runAnimation(val)
  145. } else {
  146. that._actualValue = val;
  147. that._actualPosition = that._translator.translate(val);
  148. that._move()
  149. }
  150. }
  151. }
  152. }
  153. rootElement.attr({
  154. visibility: visibility
  155. });
  156. return that
  157. },
  158. _isEnabled: null,
  159. _isVisible: null,
  160. _render: null,
  161. _clear: null,
  162. _move: null
  163. });
  164. var COEFFICIENTS_MAP = {};
  165. COEFFICIENTS_MAP["right-bottom"] = COEFFICIENTS_MAP.rb = [0, -1, -1, 0, 0, 1, 1, 0];
  166. COEFFICIENTS_MAP["bottom-right"] = COEFFICIENTS_MAP.br = [-1, 0, 0, -1, 1, 0, 0, 1];
  167. COEFFICIENTS_MAP["left-bottom"] = COEFFICIENTS_MAP.lb = [0, -1, 1, 0, 0, 1, -1, 0];
  168. COEFFICIENTS_MAP["bottom-left"] = COEFFICIENTS_MAP.bl = [1, 0, 0, -1, -1, 0, 0, 1];
  169. COEFFICIENTS_MAP["left-top"] = COEFFICIENTS_MAP.lt = [0, 1, 1, 0, 0, -1, -1, 0];
  170. COEFFICIENTS_MAP["top-left"] = COEFFICIENTS_MAP.tl = [1, 0, 0, 1, -1, 0, 0, -1];
  171. COEFFICIENTS_MAP["right-top"] = COEFFICIENTS_MAP.rt = [0, 1, -1, 0, 0, -1, 1, 0];
  172. COEFFICIENTS_MAP["top-right"] = COEFFICIENTS_MAP.tr = [-1, 0, 0, 1, 1, 0, 0, -1];
  173. function getTextCloudInfo(options) {
  174. var x = options.x;
  175. var y = options.y;
  176. var type = COEFFICIENTS_MAP[options.type];
  177. var cloudWidth = options.textWidth + 2 * options.horMargin;
  178. var cloudHeight = options.textHeight + 2 * options.verMargin;
  179. var tailWidth;
  180. var tailHeight;
  181. var cx = x;
  182. var cy = y;
  183. tailWidth = tailHeight = options.tailLength;
  184. if (1 & type[0]) {
  185. tailHeight = Math.min(tailHeight, cloudHeight / 3)
  186. } else {
  187. tailWidth = Math.min(tailWidth, cloudWidth / 3)
  188. }
  189. return {
  190. cx: _round(cx + type[0] * tailWidth + (type[0] + type[2]) * cloudWidth / 2),
  191. cy: _round(cy + type[1] * tailHeight + (type[1] + type[3]) * cloudHeight / 2),
  192. points: [_round(x), _round(y), _round(x += type[0] * (cloudWidth + tailWidth)), _round(y += type[1] * (cloudHeight + tailHeight)), _round(x += type[2] * cloudWidth), _round(y += type[3] * cloudHeight), _round(x += type[4] * cloudWidth), _round(y += type[5] * cloudHeight), _round(x += type[6] * (cloudWidth - tailWidth)), _round(y += type[7] * (cloudHeight - tailHeight))]
  193. }
  194. }
  195. var BaseTextCloudMarker = BaseIndicator.inherit({
  196. _move: function() {
  197. var that = this;
  198. var textCloudOptions = that._getTextCloudOptions();
  199. var text = _formatValue(that._actualValue, that._options.text);
  200. that._text.attr({
  201. text: text
  202. });
  203. var bBox = that._text.getBBox();
  204. var info = getTextCloudInfo({
  205. x: textCloudOptions.x,
  206. y: textCloudOptions.y,
  207. textWidth: bBox.width || text.length * that._textUnitWidth,
  208. textHeight: bBox.height || that._textHeight,
  209. horMargin: that._options.horizontalOffset,
  210. verMargin: that._options.verticalOffset,
  211. tailLength: that._options.arrowLength,
  212. type: textCloudOptions.type
  213. });
  214. that._text.attr({
  215. x: info.cx,
  216. y: info.cy + that._textVerticalOffset
  217. });
  218. that._cloud.attr({
  219. points: info.points
  220. });
  221. that._trackerElement && that._trackerElement.attr({
  222. points: info.points
  223. })
  224. },
  225. _measureText: function() {
  226. var that = this;
  227. var root;
  228. var text;
  229. var bBox;
  230. var sampleText;
  231. if (!that._textVerticalOffset) {
  232. root = that._createRoot().append(that._owner);
  233. sampleText = _getSampleText(that._translator, that._options.text);
  234. text = that._renderer.text(sampleText, 0, 0).attr({
  235. align: "center"
  236. }).css(_patchFontOptions(that._options.text.font)).append(root);
  237. bBox = text.getBBox();
  238. root.remove();
  239. that._textVerticalOffset = -bBox.y - bBox.height / 2;
  240. that._textWidth = bBox.width;
  241. that._textHeight = bBox.height;
  242. that._textUnitWidth = that._textWidth / sampleText.length;
  243. that._textFullWidth = that._textWidth + 2 * that._options.horizontalOffset;
  244. that._textFullHeight = that._textHeight + 2 * that._options.verticalOffset
  245. }
  246. },
  247. _render: function() {
  248. var that = this;
  249. that._measureText();
  250. that._cloud = that._cloud || that._renderer.path([], "area").append(that._rootElement);
  251. that._text = that._text || that._renderer.text().append(that._rootElement);
  252. that._text.attr({
  253. align: "center"
  254. }).css(_patchFontOptions(that._options.text.font))
  255. },
  256. _clear: function() {
  257. delete this._cloud;
  258. delete this._text
  259. },
  260. getTooltipParameters: function() {
  261. var position = this._getTextCloudOptions();
  262. return {
  263. x: position.x,
  264. y: position.y,
  265. value: this._currentValue,
  266. color: this._options.color
  267. }
  268. }
  269. });
  270. var BaseRangeBar = BaseIndicator.inherit({
  271. _measureText: function() {
  272. var that = this;
  273. var root;
  274. var text;
  275. var bBox;
  276. that._hasText = that._isTextVisible();
  277. if (that._hasText && !that._textVerticalOffset) {
  278. root = that._createRoot().append(that._owner);
  279. text = that._renderer.text(_getSampleText(that._translator, that._options.text), 0, 0).attr({
  280. "class": "dxg-text",
  281. align: "center"
  282. }).css(_patchFontOptions(that._options.text.font)).append(root);
  283. bBox = text.getBBox();
  284. root.remove();
  285. that._textVerticalOffset = -bBox.y - bBox.height / 2;
  286. that._textWidth = bBox.width;
  287. that._textHeight = bBox.height
  288. }
  289. },
  290. _move: function() {
  291. var that = this;
  292. that._updateBarItemsPositions();
  293. if (that._hasText) {
  294. that._text.attr({
  295. text: _formatValue(that._actualValue, that._options.text)
  296. });
  297. that._updateTextPosition();
  298. that._updateLinePosition()
  299. }
  300. },
  301. _updateBarItems: function() {
  302. var that = this;
  303. var options = that._options;
  304. var spaceColor;
  305. var translator = that._translator;
  306. that._setBarSides();
  307. that._startPosition = translator.translate(translator.getDomainStart());
  308. that._endPosition = translator.translate(translator.getDomainEnd());
  309. that._basePosition = translator.translate(options.baseValue);
  310. that._space = that._getSpace();
  311. var backgroundColor = options.backgroundColor || "none";
  312. if ("none" !== backgroundColor && that._space > 0) {
  313. spaceColor = options.containerBackgroundColor || "none"
  314. } else {
  315. that._space = 0;
  316. spaceColor = "none"
  317. }
  318. that._backItem1.attr({
  319. fill: backgroundColor
  320. });
  321. that._backItem2.attr({
  322. fill: backgroundColor
  323. });
  324. that._spaceItem1.attr({
  325. fill: spaceColor
  326. });
  327. that._spaceItem2.attr({
  328. fill: spaceColor
  329. })
  330. },
  331. _getSpace: function() {
  332. return 0
  333. },
  334. _updateTextItems: function() {
  335. var that = this;
  336. if (that._hasText) {
  337. that._line = that._line || that._renderer.path([], "line").attr({
  338. "class": "dxg-main-bar",
  339. "stroke-linecap": "square"
  340. }).append(that._rootElement);
  341. that._text = that._text || that._renderer.text("", 0, 0).attr({
  342. "class": "dxg-text"
  343. }).append(that._rootElement);
  344. that._text.attr({
  345. align: that._getTextAlign()
  346. }).css(that._getFontOptions());
  347. that._setTextItemsSides()
  348. } else {
  349. if (that._line) {
  350. that._line.remove();
  351. delete that._line
  352. }
  353. if (that._text) {
  354. that._text.remove();
  355. delete that._text
  356. }
  357. }
  358. },
  359. _isTextVisible: function() {
  360. return false
  361. },
  362. _getTextAlign: function() {
  363. return "center"
  364. },
  365. _getFontOptions: function() {
  366. var options = this._options;
  367. var font = options.text.font;
  368. if (!font || !font.color) {
  369. font = extend({}, font, {
  370. color: options.color
  371. })
  372. }
  373. return _patchFontOptions(font)
  374. },
  375. _updateBarItemsPositions: function() {
  376. var that = this;
  377. var positions = that._getPositions();
  378. that._backItem1.attr(that._buildItemSettings(positions.start, positions.back1));
  379. that._backItem2.attr(that._buildItemSettings(positions.back2, positions.end));
  380. that._spaceItem1.attr(that._buildItemSettings(positions.back1, positions.main1));
  381. that._spaceItem2.attr(that._buildItemSettings(positions.main2, positions.back2));
  382. that._mainItem.attr(that._buildItemSettings(positions.main1, positions.main2));
  383. that._trackerElement && that._trackerElement.attr(that._buildItemSettings(positions.main1, positions.main2))
  384. },
  385. _render: function() {
  386. var that = this;
  387. that._measureText();
  388. if (!that._backItem1) {
  389. that._backItem1 = that._createBarItem();
  390. that._backItem1.attr({
  391. "class": "dxg-back-bar"
  392. })
  393. }
  394. if (!that._backItem2) {
  395. that._backItem2 = that._createBarItem();
  396. that._backItem2.attr({
  397. "class": "dxg-back-bar"
  398. })
  399. }
  400. if (!that._spaceItem1) {
  401. that._spaceItem1 = that._createBarItem();
  402. that._spaceItem1.attr({
  403. "class": "dxg-space-bar"
  404. })
  405. }
  406. if (!that._spaceItem2) {
  407. that._spaceItem2 = that._createBarItem();
  408. that._spaceItem2.attr({
  409. "class": "dxg-space-bar"
  410. })
  411. }
  412. if (!that._mainItem) {
  413. that._mainItem = that._createBarItem();
  414. that._mainItem.attr({
  415. "class": "dxg-main-bar"
  416. })
  417. }
  418. that._updateBarItems();
  419. that._updateTextItems()
  420. },
  421. _clear: function() {
  422. var that = this;
  423. delete that._backItem1;
  424. delete that._backItem2;
  425. delete that._spaceItem1;
  426. delete that._spaceItem2;
  427. delete that._mainItem;
  428. delete that._hasText;
  429. delete that._line;
  430. delete that._text
  431. },
  432. getTooltipParameters: function() {
  433. var position = this._getTooltipPosition();
  434. return {
  435. x: position.x,
  436. y: position.y,
  437. value: this._currentValue,
  438. color: this._options.color,
  439. offset: 0
  440. }
  441. }
  442. });
  443. exports.BaseElement = BaseElement;
  444. exports.BaseIndicator = BaseIndicator;
  445. exports.BaseTextCloudMarker = BaseTextCloudMarker;
  446. exports.BaseRangeBar = BaseRangeBar;