bar_gauge.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645
  1. /**
  2. * DevExtreme (viz/gauges/bar_gauge.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 PI_DIV_180 = Math.PI / 180;
  11. var _abs = Math.abs;
  12. var _round = Math.round;
  13. var _floor = Math.floor;
  14. var _min = Math.min;
  15. var _max = Math.max;
  16. var registerComponent = require("../../core/component_registrator");
  17. var objectUtils = require("../../core/utils/object");
  18. var commonUtils = require("../../core/utils/common");
  19. var extend = require("../../core/utils/extend").extend;
  20. var _normalizeEnum = require("../core/utils").normalizeEnum;
  21. var baseGaugeModule = require("./base_gauge");
  22. var dxBaseGauge = baseGaugeModule.dxBaseGauge;
  23. var _getSampleText = baseGaugeModule.getSampleText;
  24. var _formatValue = baseGaugeModule.formatValue;
  25. var _compareArrays = baseGaugeModule.compareArrays;
  26. var dxCircularGauge = require("./circular_gauge");
  27. var _isArray = Array.isArray;
  28. var vizUtils = require("../core/utils");
  29. var _convertAngleToRendererSpace = vizUtils.convertAngleToRendererSpace;
  30. var _getCosAndSin = vizUtils.getCosAndSin;
  31. var _patchFontOptions = vizUtils.patchFontOptions;
  32. var _Number = Number;
  33. var _isFinite = isFinite;
  34. var _noop = commonUtils.noop;
  35. var _extend = extend;
  36. var OPTION_VALUES = "values";
  37. var dxBarGauge = dxBaseGauge.inherit({
  38. _rootClass: "dxbg-bar-gauge",
  39. _themeSection: "barGauge",
  40. _fontFields: ["label.font", "legend.font", "legend.title.font", "legend.title.subtitle.font"],
  41. _initCore: function() {
  42. var that = this;
  43. that.callBase.apply(that, arguments);
  44. that._barsGroup = that._renderer.g().attr({
  45. "class": "dxbg-bars"
  46. }).linkOn(that._renderer.root, "bars");
  47. that._values = [];
  48. that._context = {
  49. renderer: that._renderer,
  50. translator: that._translator,
  51. tracker: that._tracker,
  52. group: that._barsGroup
  53. };
  54. that._animateStep = function(pos) {
  55. var bars = that._bars;
  56. var i;
  57. var ii;
  58. for (i = 0, ii = bars.length; i < ii; ++i) {
  59. bars[i].animate(pos)
  60. }
  61. };
  62. that._animateComplete = function() {
  63. that._bars.forEach(function(bar) {
  64. return bar.endAnimation()
  65. });
  66. that._checkOverlap()
  67. }
  68. },
  69. _disposeCore: function() {
  70. var that = this;
  71. that._barsGroup.linkOff();
  72. that._barsGroup = that._values = that._context = that._animateStep = that._animateComplete = null;
  73. that.callBase.apply(that, arguments)
  74. },
  75. _setupDomainCore: function() {
  76. var that = this;
  77. var startValue = that.option("startValue");
  78. var endValue = that.option("endValue");
  79. _isFinite(startValue) || (startValue = 0);
  80. _isFinite(endValue) || (endValue = 100);
  81. that._translator.setDomain(startValue, endValue);
  82. that._baseValue = that._translator.adjust(that.option("baseValue"));
  83. _isFinite(that._baseValue) || (that._baseValue = startValue < endValue ? startValue : endValue)
  84. },
  85. _getDefaultSize: function() {
  86. return {
  87. width: 300,
  88. height: 300
  89. }
  90. },
  91. _setupCodomain: dxCircularGauge.prototype._setupCodomain,
  92. _getApproximateScreenRange: function() {
  93. var that = this;
  94. var sides = that._area.sides;
  95. var width = that._canvas.width / (sides.right - sides.left);
  96. var height = that._canvas.height / (sides.down - sides.up);
  97. var r = width < height ? width : height;
  98. return -that._translator.getCodomainRange() * r * PI_DIV_180
  99. },
  100. _setupAnimationSettings: function() {
  101. var that = this;
  102. that.callBase.apply(that, arguments);
  103. if (that._animationSettings) {
  104. that._animationSettings.step = that._animateStep;
  105. that._animationSettings.complete = that._animateComplete
  106. }
  107. },
  108. _cleanContent: function() {
  109. var that = this;
  110. that._barsGroup.linkRemove();
  111. that._animationSettings && that._barsGroup.stopAnimation();
  112. that._barsGroup.clear()
  113. },
  114. _renderContent: function() {
  115. var that = this;
  116. var labelOptions = that.option("label");
  117. var text;
  118. var bBox;
  119. var context = that._context;
  120. that._barsGroup.linkAppend();
  121. context.textEnabled = void 0 === labelOptions || labelOptions && (!("visible" in labelOptions) || labelOptions.visible);
  122. if (context.textEnabled) {
  123. context.textColor = labelOptions && labelOptions.font && labelOptions.font.color || null;
  124. labelOptions = _extend(true, {}, that._themeManager.theme().label, labelOptions);
  125. context.formatOptions = {
  126. format: void 0 !== labelOptions.format ? labelOptions.format : that._defaultFormatOptions,
  127. customizeText: labelOptions.customizeText
  128. };
  129. context.textOptions = {
  130. align: "center"
  131. };
  132. context.fontStyles = _patchFontOptions(_extend({}, that._themeManager.theme().label.font, labelOptions.font, {
  133. color: null
  134. }));
  135. that._textIndent = labelOptions.indent > 0 ? _Number(labelOptions.indent) : 0;
  136. context.lineWidth = labelOptions.connectorWidth > 0 ? _Number(labelOptions.connectorWidth) : 0;
  137. context.lineColor = labelOptions.connectorColor || null;
  138. text = that._renderer.text(_getSampleText(that._translator, context.formatOptions), 0, 0).attr(context.textOptions).css(context.fontStyles).append(that._barsGroup);
  139. bBox = text.getBBox();
  140. text.remove();
  141. context.textY = bBox.y;
  142. context.textWidth = bBox.width;
  143. context.textHeight = bBox.height
  144. }
  145. dxCircularGauge.prototype._applyMainLayout.call(that);
  146. that._renderBars()
  147. },
  148. _measureMainElements: function() {
  149. var result = {
  150. maxRadius: this._area.radius
  151. };
  152. if (this._context.textEnabled) {
  153. result.horizontalMargin = this._context.textWidth;
  154. result.verticalMargin = this._context.textHeight;
  155. result.inverseHorizontalMargin = this._context.textWidth / 2;
  156. result.inverseVerticalMargin = this._context.textHeight / 2
  157. }
  158. return result
  159. },
  160. _renderBars: function() {
  161. var that = this;
  162. var options = _extend({}, that._themeManager.theme(), that.option());
  163. var radius;
  164. var area = that._area;
  165. var relativeInnerRadius = options.relativeInnerRadius > 0 && options.relativeInnerRadius < 1 ? _Number(options.relativeInnerRadius) : .1;
  166. radius = area.radius;
  167. if (that._context.textEnabled) {
  168. that._textIndent = _round(_min(that._textIndent, radius / 2));
  169. radius -= that._textIndent
  170. }
  171. that._outerRadius = _floor(radius);
  172. that._innerRadius = _floor(radius * relativeInnerRadius);
  173. that._barSpacing = options.barSpacing > 0 ? _Number(options.barSpacing) : 0;
  174. _extend(that._context, {
  175. backgroundColor: options.backgroundColor,
  176. x: area.x,
  177. y: area.y,
  178. startAngle: area.startCoord,
  179. endAngle: area.endCoord,
  180. baseAngle: that._translator.translate(that._baseValue)
  181. });
  182. that._arrangeBars()
  183. },
  184. _arrangeBars: function() {
  185. var that = this;
  186. var radius = that._outerRadius - that._innerRadius;
  187. var context = that._context;
  188. var i;
  189. var count = that._bars.length;
  190. that._beginValueChanging();
  191. context.barSize = count > 0 ? _max((radius - (count - 1) * that._barSpacing) / count, 1) : 0;
  192. var spacing = count > 1 ? _max(_min((radius - count * context.barSize) / (count - 1), that._barSpacing), 0) : 0;
  193. var _count = _min(_floor((radius + spacing) / context.barSize), count);
  194. that._setBarsCount(count);
  195. radius = that._outerRadius;
  196. context.textRadius = radius;
  197. context.textIndent = that._textIndent;
  198. that._palette.reset();
  199. var unitOffset = context.barSize + spacing;
  200. var colors = that._palette.generateColors(_count);
  201. for (i = 0; i < _count; ++i, radius -= unitOffset) {
  202. that._bars[i].arrange({
  203. radius: radius,
  204. color: colors[i]
  205. })
  206. }
  207. for (var _i = _count; _i < count; _i++) {
  208. that._bars[_i].hide()
  209. }
  210. if (that._animationSettings && !that._noAnimation) {
  211. that._animateBars()
  212. } else {
  213. that._updateBars()
  214. }
  215. that._endValueChanging()
  216. },
  217. _setBarsCount: function() {
  218. var that = this;
  219. if (that._bars.length > 0) {
  220. if (that._dummyBackground) {
  221. that._dummyBackground.dispose();
  222. that._dummyBackground = null
  223. }
  224. } else {
  225. if (!that._dummyBackground) {
  226. that._dummyBackground = that._renderer.arc().attr({
  227. "stroke-linejoin": "round"
  228. })
  229. }
  230. that._dummyBackground.attr({
  231. x: that._context.x,
  232. y: that._context.y,
  233. outerRadius: that._outerRadius,
  234. innerRadius: that._innerRadius,
  235. startAngle: that._context.endAngle,
  236. endAngle: that._context.startAngle,
  237. fill: that._context.backgroundColor
  238. }).append(that._barsGroup)
  239. }
  240. },
  241. _updateBars: function() {
  242. this._bars.forEach(function(bar) {
  243. return bar.applyValue()
  244. });
  245. this._checkOverlap()
  246. },
  247. _checkOverlap: function() {
  248. var that = this;
  249. var bars = that._bars;
  250. var overlapStrategy = _normalizeEnum(that._getOption("resolveLabelOverlapping", true));
  251. if ("none" === overlapStrategy) {
  252. return
  253. }
  254. var sortedBars = bars.concat().sort(function(a, b) {
  255. return a.getValue() - b.getValue()
  256. });
  257. var currentIndex = 0;
  258. var nextIndex = 1;
  259. while (currentIndex < sortedBars.length && nextIndex < sortedBars.length) {
  260. var current = sortedBars[currentIndex];
  261. var next = sortedBars[nextIndex];
  262. if (current.checkIntersect(next)) {
  263. next.hideLabel();
  264. nextIndex++
  265. } else {
  266. currentIndex = nextIndex;
  267. nextIndex = currentIndex + 1
  268. }
  269. }
  270. },
  271. _animateBars: function() {
  272. var that = this;
  273. var i;
  274. var ii = that._bars.length;
  275. if (ii > 0) {
  276. for (i = 0; i < ii; ++i) {
  277. that._bars[i].beginAnimation()
  278. }
  279. that._barsGroup.animate({
  280. _: 0
  281. }, that._animationSettings)
  282. }
  283. },
  284. _buildNodes: function() {
  285. var that = this;
  286. var options = that._options;
  287. that._palette = that._themeManager.createPalette(options.palette, {
  288. useHighlight: true,
  289. extensionMode: options.paletteExtensionMode
  290. });
  291. that._palette.reset();
  292. that._bars = that._bars || [];
  293. that._animationSettings && that._barsGroup.stopAnimation();
  294. var barValues = that._values.filter(_isFinite);
  295. var count = barValues.length;
  296. if (that._bars.length > count) {
  297. var ii = that._bars.length;
  298. for (var i = count; i < ii; ++i) {
  299. that._bars[i].dispose()
  300. }
  301. that._bars.splice(count, ii - count)
  302. } else {
  303. if (that._bars.length < count) {
  304. for (var _i2 = that._bars.length; _i2 < count; ++_i2) {
  305. that._bars.push(new BarWrapper(_i2, that._context))
  306. }
  307. }
  308. }
  309. that._bars.forEach(function(bar, index) {
  310. bar.update({
  311. color: that._palette.getNextColor(count),
  312. value: barValues[index]
  313. })
  314. })
  315. },
  316. _updateValues: function(values) {
  317. var that = this;
  318. var list = _isArray(values) && values || _isFinite(values) && [values] || [];
  319. var i;
  320. var ii = list.length;
  321. var value;
  322. that._values.length = ii;
  323. for (i = 0; i < ii; ++i) {
  324. value = list[i];
  325. that._values[i] = value = _Number(_isFinite(value) ? value : that._values[i])
  326. }
  327. if (!that._resizing) {
  328. if (!_compareArrays(that._values, that.option(OPTION_VALUES))) {
  329. that.option(OPTION_VALUES, that._values.slice())
  330. }
  331. }
  332. this._change(["NODES"])
  333. },
  334. values: function(arg) {
  335. if (void 0 !== arg) {
  336. this._updateValues(arg);
  337. return this
  338. } else {
  339. return this._values.slice(0)
  340. }
  341. },
  342. _optionChangesMap: {
  343. backgroundColor: "MOSTLY_TOTAL",
  344. relativeInnerRadius: "MOSTLY_TOTAL",
  345. barSpacing: "MOSTLY_TOTAL",
  346. label: "MOSTLY_TOTAL",
  347. resolveLabelOverlapping: "MOSTLY_TOTAL",
  348. palette: "MOSTLY_TOTAL",
  349. paletteExtensionMode: "MOSTLY_TOTAL",
  350. values: "VALUES"
  351. },
  352. _change_VALUES: function() {
  353. this._updateValues(this.option(OPTION_VALUES))
  354. },
  355. _factory: objectUtils.clone(dxBaseGauge.prototype._factory),
  356. _optionChangesOrder: ["VALUES", "NODES"],
  357. _initialChanges: ["VALUES"],
  358. _change_NODES: function() {
  359. this._buildNodes()
  360. },
  361. _change_MOSTLY_TOTAL: function() {
  362. this._change(["NODES"]);
  363. this.callBase()
  364. },
  365. _proxyData: [],
  366. _getLegendData: function() {
  367. var that = this;
  368. var formatOptions = {};
  369. var options = that._options;
  370. var labelFormatOptions = (options.label || {}).format;
  371. var legendFormatOptions = (options.legend || {}).itemTextFormat;
  372. if (legendFormatOptions) {
  373. formatOptions.format = legendFormatOptions
  374. } else {
  375. formatOptions.format = labelFormatOptions || that._defaultFormatOptions
  376. }
  377. return (this._bars || []).map(function(b) {
  378. return {
  379. id: b.index,
  380. item: {
  381. value: b.getValue(),
  382. color: b.getColor(),
  383. index: b.index
  384. },
  385. text: _formatValue(b.getValue(), formatOptions),
  386. visible: true,
  387. states: {
  388. normal: {
  389. fill: b.getColor()
  390. }
  391. }
  392. }
  393. })
  394. }
  395. });
  396. var BarWrapper = function(index, context) {
  397. var that = this;
  398. that._context = context;
  399. that._tracker = context.renderer.arc().attr({
  400. "stroke-linejoin": "round"
  401. });
  402. that.index = index
  403. };
  404. _extend(BarWrapper.prototype, {
  405. dispose: function() {
  406. var that = this;
  407. that._background.dispose();
  408. that._bar.dispose();
  409. if (that._context.textEnabled) {
  410. that._line.dispose();
  411. that._text.dispose()
  412. }
  413. that._context.tracker.detach(that._tracker);
  414. that._context = that._settings = that._background = that._bar = that._line = that._text = that._tracker = null;
  415. return that
  416. },
  417. arrange: function(options) {
  418. var that = this;
  419. var context = that._context;
  420. this._visible = true;
  421. context.tracker.attach(that._tracker, that, {
  422. index: that.index
  423. });
  424. that._background = context.renderer.arc().attr({
  425. "stroke-linejoin": "round",
  426. fill: context.backgroundColor
  427. }).append(context.group);
  428. that._settings = that._settings || {
  429. x: context.x,
  430. y: context.y,
  431. startAngle: context.baseAngle,
  432. endAngle: context.baseAngle
  433. };
  434. that._bar = context.renderer.arc().attr(_extend({
  435. "stroke-linejoin": "round"
  436. }, that._settings)).append(context.group);
  437. if (context.textEnabled) {
  438. that._line = context.renderer.path([], "line").attr({
  439. "stroke-width": context.lineWidth
  440. }).append(context.group);
  441. that._text = context.renderer.text().css(context.fontStyles).attr(context.textOptions).append(context.group)
  442. }
  443. that._angle = isFinite(that._angle) ? that._angle : context.baseAngle;
  444. that._settings.outerRadius = options.radius;
  445. that._settings.innerRadius = options.radius - context.barSize;
  446. that._settings.x = context.x;
  447. that._settings.y = context.y;
  448. that._background.attr(_extend({}, that._settings, {
  449. startAngle: context.endAngle,
  450. endAngle: context.startAngle,
  451. fill: that._context.backgroundColor
  452. }));
  453. that._bar.attr({
  454. x: context.x,
  455. y: context.y,
  456. outerRadius: that._settings.outerRadius,
  457. innerRadius: that._settings.innerRadius,
  458. fill: that._color
  459. });
  460. that._tracker.attr(that._settings);
  461. if (context.textEnabled) {
  462. that._line.attr({
  463. points: [context.x, context.y - that._settings.innerRadius, context.x, context.y - context.textRadius - context.textIndent],
  464. stroke: context.lineColor || that._color
  465. }).sharp();
  466. that._text.css({
  467. fill: context.textColor || that._color
  468. })
  469. }
  470. return that
  471. },
  472. getTooltipParameters: function() {
  473. var that = this;
  474. var cosSin = _getCosAndSin((that._angle + that._context.baseAngle) / 2);
  475. return {
  476. x: _round(that._context.x + (that._settings.outerRadius + that._settings.innerRadius) / 2 * cosSin.cos),
  477. y: _round(that._context.y - (that._settings.outerRadius + that._settings.innerRadius) / 2 * cosSin.sin),
  478. offset: 0,
  479. color: that._color,
  480. value: that._value
  481. }
  482. },
  483. setAngle: function(angle) {
  484. var that = this;
  485. var context = that._context;
  486. var settings = that._settings;
  487. var cosSin;
  488. that._angle = angle;
  489. setAngles(settings, context.baseAngle, angle);
  490. that._bar.attr(settings);
  491. that._tracker.attr(settings);
  492. if (context.textEnabled) {
  493. cosSin = _getCosAndSin(angle);
  494. var indent = context.textIndent;
  495. var radius = context.textRadius + indent;
  496. var x = context.x + radius * cosSin.cos;
  497. var y = context.y - radius * cosSin.sin;
  498. var halfWidth = .5 * context.textWidth;
  499. var textHeight = context.textHeight;
  500. var textY = context.textY;
  501. if (_abs(x - context.x) > indent) {
  502. x += x < context.x ? -halfWidth : halfWidth
  503. }
  504. if (_abs(y - context.y) <= indent) {
  505. y -= textY + .5 * textHeight
  506. } else {
  507. y -= y < context.y ? textY + textHeight : textY
  508. }
  509. var text = _formatValue(that._value, context.formatOptions, {
  510. index: that.index
  511. });
  512. var visibility = "" === text ? "hidden" : null;
  513. that._text.attr({
  514. text: text,
  515. x: x,
  516. y: y,
  517. visibility: visibility
  518. });
  519. that._line.attr({
  520. visibility: visibility
  521. });
  522. that._line.rotate(_convertAngleToRendererSpace(angle), context.x, context.y)
  523. }
  524. return that
  525. },
  526. hideLabel: function() {
  527. this._text.attr({
  528. visibility: "hidden"
  529. });
  530. this._line.attr({
  531. visibility: "hidden"
  532. })
  533. },
  534. checkIntersect: function(anotherBar) {
  535. var coords = this.calculateLabelCoords();
  536. var anotherCoords = anotherBar.calculateLabelCoords();
  537. if (!coords || !anotherCoords) {
  538. return false
  539. }
  540. var width = Math.max(0, Math.min(coords.bottomRight.x, anotherCoords.bottomRight.x) - Math.max(coords.topLeft.x, anotherCoords.topLeft.x));
  541. var height = Math.max(0, Math.min(coords.bottomRight.y, anotherCoords.bottomRight.y) - Math.max(coords.topLeft.y, anotherCoords.topLeft.y));
  542. return width * height !== 0
  543. },
  544. calculateLabelCoords: function() {
  545. if (!this._text) {
  546. return
  547. }
  548. var box = this._text.getBBox();
  549. return {
  550. topLeft: {
  551. x: box.x,
  552. y: box.y
  553. },
  554. bottomRight: {
  555. x: box.x + box.width,
  556. y: box.y + box.height
  557. }
  558. }
  559. },
  560. _processValue: function(value) {
  561. return this._context.translator.translate(this._context.translator.adjust(value))
  562. },
  563. applyValue: function() {
  564. if (!this._visible) {
  565. return this
  566. }
  567. return this.setAngle(this._processValue(this.getValue()))
  568. },
  569. update: function(_ref) {
  570. var color = _ref.color,
  571. value = _ref.value;
  572. this._color = color;
  573. this._value = value
  574. },
  575. hide: function() {
  576. this._visible = false
  577. },
  578. getColor: function() {
  579. return this._color
  580. },
  581. getValue: function() {
  582. return this._value
  583. },
  584. beginAnimation: function() {
  585. if (!this._visible) {
  586. return this
  587. }
  588. var that = this;
  589. var angle = this._processValue(this.getValue());
  590. if (!compareFloats(that._angle, angle)) {
  591. that._start = that._angle;
  592. that._delta = angle - that._angle;
  593. that._tracker.attr({
  594. visibility: "hidden"
  595. });
  596. if (that._context.textEnabled) {
  597. that._line.attr({
  598. visibility: "hidden"
  599. });
  600. that._text.attr({
  601. visibility: "hidden"
  602. })
  603. }
  604. } else {
  605. that.animate = _noop;
  606. that.setAngle(that._angle)
  607. }
  608. },
  609. animate: function(pos) {
  610. if (!this._visible) {
  611. return this
  612. }
  613. var that = this;
  614. that._angle = that._start + that._delta * pos;
  615. setAngles(that._settings, that._context.baseAngle, that._angle);
  616. that._bar.attr(that._settings)
  617. },
  618. endAnimation: function() {
  619. var that = this;
  620. if (void 0 !== that._delta) {
  621. if (compareFloats(that._angle, that._start + that._delta)) {
  622. that._tracker.attr({
  623. visibility: null
  624. });
  625. that.setAngle(that._angle)
  626. }
  627. } else {
  628. delete that.animate
  629. }
  630. delete that._start;
  631. delete that._delta
  632. }
  633. });
  634. function setAngles(target, angle1, angle2) {
  635. target.startAngle = angle1 < angle2 ? angle1 : angle2;
  636. target.endAngle = angle1 < angle2 ? angle2 : angle1
  637. }
  638. function compareFloats(value1, value2) {
  639. return _abs(value1 - value2) < 1e-4
  640. }
  641. registerComponent("dxBarGauge", dxBarGauge);
  642. exports.dxBarGauge = dxBarGauge;
  643. dxBarGauge.addPlugin(require("../components/legend").plugin);