xy_axes.js 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225
  1. /**
  2. * DevExtreme (viz/axes/xy_axes.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 _range = require("../translators/range");
  11. var _range2 = _interopRequireDefault(_range);
  12. var _format_helper = require("../../format_helper");
  13. var _date = require("../../core/utils/date");
  14. var _date2 = _interopRequireDefault(_date);
  15. var _extend = require("../../core/utils/extend");
  16. var _datetime_breaks = require("./datetime_breaks");
  17. var _common = require("../../core/utils/common");
  18. var _utils = require("../core/utils");
  19. var _utils2 = _interopRequireDefault(_utils);
  20. var _type = require("../../core/utils/type");
  21. var _axes_constants = require("./axes_constants");
  22. var _axes_constants2 = _interopRequireDefault(_axes_constants);
  23. function _interopRequireDefault(obj) {
  24. return obj && obj.__esModule ? obj : {
  25. "default": obj
  26. }
  27. }
  28. var getNextDateUnit = _date2.default.getNextDateUnit;
  29. var correctDateWithUnitBeginning = _date2.default.correctDateWithUnitBeginning;
  30. var _math = Math;
  31. var _max = _math.max;
  32. var TOP = _axes_constants2.default.top;
  33. var BOTTOM = _axes_constants2.default.bottom;
  34. var LEFT = _axes_constants2.default.left;
  35. var RIGHT = _axes_constants2.default.right;
  36. var CENTER = _axes_constants2.default.center;
  37. var SCALE_BREAK_OFFSET = 3;
  38. var RANGE_RATIO = .3;
  39. var WAVED_LINE_CENTER = 2;
  40. var WAVED_LINE_TOP = 0;
  41. var WAVED_LINE_BOTTOM = 4;
  42. var WAVED_LINE_LENGTH = 24;
  43. var TICKS_CORRECTIONS = {
  44. left: -1,
  45. top: -1,
  46. right: 0,
  47. bottom: 0,
  48. center: -.5
  49. };
  50. function prepareDatesDifferences(datesDifferences, tickInterval) {
  51. var dateUnitInterval;
  52. var i;
  53. if ("week" === tickInterval) {
  54. tickInterval = "day"
  55. }
  56. if ("quarter" === tickInterval) {
  57. tickInterval = "month"
  58. }
  59. if (datesDifferences[tickInterval]) {
  60. for (i = 0; i < _date2.default.dateUnitIntervals.length; i++) {
  61. dateUnitInterval = _date2.default.dateUnitIntervals[i];
  62. if (datesDifferences[dateUnitInterval]) {
  63. datesDifferences[dateUnitInterval] = false;
  64. datesDifferences.count--
  65. }
  66. if (dateUnitInterval === tickInterval) {
  67. break
  68. }
  69. }
  70. }
  71. }
  72. function sortingBreaks(breaks) {
  73. return breaks.sort(function(a, b) {
  74. return a.from - b.from
  75. })
  76. }
  77. function filterBreaks(breaks, viewport, breakStyle) {
  78. var minVisible = viewport.minVisible;
  79. var maxVisible = viewport.maxVisible;
  80. var breakSize = breakStyle ? breakStyle.width : 0;
  81. return breaks.reduce(function(result, currentBreak) {
  82. var from = currentBreak.from;
  83. var to = currentBreak.to;
  84. var lastResult = result[result.length - 1];
  85. var newBreak;
  86. if (!(0, _type.isDefined)(from) || !(0, _type.isDefined)(to)) {
  87. return result
  88. }
  89. if (from > to) {
  90. to = [from, from = to][0]
  91. }
  92. if (result.length && from < lastResult.to) {
  93. if (to > lastResult.to) {
  94. lastResult.to = to > maxVisible ? maxVisible : to;
  95. if (lastResult.gapSize) {
  96. lastResult.gapSize = void 0;
  97. lastResult.cumulativeWidth += breakSize
  98. }
  99. }
  100. } else {
  101. if ((from >= minVisible && from < maxVisible || to <= maxVisible && to > minVisible) && to - from < maxVisible - minVisible) {
  102. from = from >= minVisible ? from : minVisible;
  103. to = to <= maxVisible ? to : maxVisible;
  104. newBreak = {
  105. from: from,
  106. to: to,
  107. cumulativeWidth: (lastResult ? lastResult.cumulativeWidth : 0) + breakSize
  108. };
  109. if (currentBreak.gapSize) {
  110. newBreak.gapSize = _date2.default.convertMillisecondsToDateUnits(to - from);
  111. newBreak.cumulativeWidth = lastResult ? lastResult.cumulativeWidth : 0
  112. }
  113. result.push(newBreak)
  114. }
  115. }
  116. return result
  117. }, [])
  118. }
  119. function getMarkerDates(min, max, markerInterval) {
  120. var origMin = min;
  121. var dates;
  122. min = correctDateWithUnitBeginning(min, markerInterval);
  123. max = correctDateWithUnitBeginning(max, markerInterval);
  124. dates = _date2.default.getSequenceByInterval(min, max, markerInterval);
  125. if (dates.length && origMin > dates[0]) {
  126. dates = dates.slice(1)
  127. }
  128. return dates
  129. }
  130. function getStripHorizontalAlignmentPosition(alignment) {
  131. var position = "start";
  132. if ("center" === alignment) {
  133. position = "center"
  134. }
  135. if ("right" === alignment) {
  136. position = "end"
  137. }
  138. return position
  139. }
  140. function getStripVerticalAlignmentPosition(alignment) {
  141. var position = "start";
  142. if ("center" === alignment) {
  143. position = "center"
  144. }
  145. if ("bottom" === alignment) {
  146. position = "end"
  147. }
  148. return position
  149. }
  150. function getMarkerInterval(tickInterval) {
  151. var markerInterval = getNextDateUnit(tickInterval);
  152. if ("quarter" === markerInterval) {
  153. markerInterval = getNextDateUnit(markerInterval)
  154. }
  155. return markerInterval
  156. }
  157. function getMarkerFormat(curDate, prevDate, tickInterval, markerInterval) {
  158. var format = markerInterval;
  159. var datesDifferences = prevDate && _date2.default.getDatesDifferences(prevDate, curDate);
  160. if (prevDate && "year" !== tickInterval) {
  161. prepareDatesDifferences(datesDifferences, tickInterval);
  162. format = (0, _format_helper.getDateFormatByDifferences)(datesDifferences)
  163. }
  164. return format
  165. }
  166. function getMaxSide(act, boxes) {
  167. return boxes.reduce(function(prevValue, box) {
  168. return _max(prevValue, act(box))
  169. }, 0)
  170. }
  171. function getDistanceByAngle(bBox, rotationAngle) {
  172. rotationAngle = _math.abs(rotationAngle);
  173. rotationAngle = rotationAngle % 180 >= 90 ? 90 - rotationAngle % 90 : rotationAngle % 90;
  174. var a = rotationAngle * (_math.PI / 180);
  175. if (a >= _math.atan(bBox.height / bBox.width)) {
  176. return bBox.height / _math.abs(_math.sin(a))
  177. } else {
  178. return bBox.width
  179. }
  180. }
  181. function getMaxConstantLinePadding(constantLines) {
  182. return constantLines.reduce(function(padding, options) {
  183. return _max(padding, options.paddingTopBottom)
  184. }, 0)
  185. }
  186. function getConstantLineLabelMarginForVerticalAlignment(constantLines, alignment, labelHeight) {
  187. return constantLines.some(function(options) {
  188. return options.label.verticalAlignment === alignment
  189. }) && labelHeight || 0
  190. }
  191. function getLeftMargin(bBox) {
  192. return _math.abs(bBox.x) || 0
  193. }
  194. function getRightMargin(bBox) {
  195. return _math.abs(bBox.width - _math.abs(bBox.x)) || 0
  196. }
  197. function generateRangesOnPoints(points, edgePoints, getRange) {
  198. var i;
  199. var length;
  200. var maxRange = null;
  201. var ranges = [];
  202. var curValue;
  203. var prevValue;
  204. var curRange;
  205. for (i = 1, length = points.length; i < length; i++) {
  206. curValue = points[i];
  207. prevValue = points[i - 1];
  208. curRange = getRange(curValue, prevValue);
  209. if (edgePoints.indexOf(curValue) >= 0) {
  210. if (!maxRange || curRange > maxRange.length) {
  211. maxRange = {
  212. start: curValue,
  213. end: prevValue,
  214. length: curRange
  215. }
  216. }
  217. } else {
  218. if (maxRange && curRange < maxRange.length) {
  219. ranges.push(maxRange)
  220. } else {
  221. ranges.push({
  222. start: curValue,
  223. end: prevValue,
  224. length: curRange
  225. })
  226. }
  227. maxRange = null
  228. }
  229. }
  230. if (maxRange) {
  231. ranges.push(maxRange)
  232. }
  233. return ranges
  234. }
  235. function generateAutoBreaks(_ref, series, _ref2) {
  236. var logarithmBase = _ref.logarithmBase,
  237. type = _ref.type,
  238. maxAutoBreakCount = _ref.maxAutoBreakCount;
  239. var minVisible = _ref2.minVisible,
  240. maxVisible = _ref2.maxVisible;
  241. var breaks = [];
  242. var getRange = "logarithmic" === type ? function(min, max) {
  243. return _utils2.default.getLog(max / min, logarithmBase)
  244. } : function(min, max) {
  245. return max - min
  246. };
  247. var visibleRange = getRange(minVisible, maxVisible);
  248. var points = series.reduce(function(result, s) {
  249. var points = s.getPointsInViewPort();
  250. result[0] = result[0].concat(points[0]);
  251. result[1] = result[1].concat(points[1]);
  252. return result
  253. }, [
  254. [],
  255. []
  256. ]);
  257. var sortedAllPoints = points[0].concat(points[1]).sort(function(a, b) {
  258. return b - a
  259. });
  260. var edgePoints = points[1].filter(function(p) {
  261. return points[0].indexOf(p) < 0
  262. });
  263. var minDiff = RANGE_RATIO * visibleRange;
  264. var ranges = generateRangesOnPoints(sortedAllPoints, edgePoints, getRange).sort(function(a, b) {
  265. return b.length - a.length
  266. });
  267. var epsilon = _math.min.apply(null, ranges.map(function(r) {
  268. return r.length
  269. })) / 1e3;
  270. var _maxAutoBreakCount = (0, _type.isDefined)(maxAutoBreakCount) ? _math.min(maxAutoBreakCount, ranges.length) : ranges.length;
  271. for (var i = 0; i < _maxAutoBreakCount; i++) {
  272. if (ranges[i].length >= minDiff) {
  273. if (visibleRange <= ranges[i].length) {
  274. break
  275. }
  276. visibleRange -= ranges[i].length;
  277. if (visibleRange > epsilon || visibleRange < -epsilon) {
  278. breaks.push({
  279. from: ranges[i].start,
  280. to: ranges[i].end
  281. });
  282. minDiff = RANGE_RATIO * visibleRange
  283. }
  284. } else {
  285. break
  286. }
  287. }
  288. sortingBreaks(breaks);
  289. return breaks
  290. }
  291. module.exports = {
  292. linear: {
  293. _getStep: function(boxes, rotationAngle) {
  294. var spacing = this._options.label.minSpacing;
  295. var func = this._isHorizontal ? function(box) {
  296. return box.width + spacing
  297. } : function(box) {
  298. return box.height
  299. };
  300. var maxLabelLength = getMaxSide(func, boxes);
  301. if (rotationAngle) {
  302. maxLabelLength = getDistanceByAngle({
  303. width: maxLabelLength,
  304. height: this._getMaxLabelHeight(boxes, 0)
  305. }, rotationAngle)
  306. }
  307. return _axes_constants2.default.getTicksCountInRange(this._majorTicks, this._isHorizontal ? "x" : "y", maxLabelLength)
  308. },
  309. _getMaxLabelHeight: function(boxes, spacing) {
  310. return getMaxSide(function(box) {
  311. return box.height
  312. }, boxes) + spacing
  313. },
  314. _validateOverlappingMode: function(mode, displayMode) {
  315. if (this._isHorizontal && ("rotate" === displayMode || "stagger" === displayMode) || !this._isHorizontal) {
  316. return _axes_constants2.default.validateOverlappingMode(mode)
  317. }
  318. return mode
  319. },
  320. _validateDisplayMode: function(mode) {
  321. return this._isHorizontal ? mode : "standard"
  322. },
  323. getMarkerTrackers: function() {
  324. return this._markerTrackers
  325. },
  326. _getSharpParam: function(opposite) {
  327. return this._isHorizontal ^ opposite ? "h" : "v"
  328. },
  329. _createAxisElement: function() {
  330. return this._renderer.path([], "line")
  331. },
  332. _updateAxisElementPosition: function() {
  333. var axisCoord = this._axisPosition;
  334. var canvas = this._getCanvasStartEnd();
  335. this._axisElement.attr({
  336. points: this._isHorizontal ? [canvas.start, axisCoord, canvas.end, axisCoord] : [axisCoord, canvas.start, axisCoord, canvas.end]
  337. })
  338. },
  339. _getTranslatedCoord: function(value, offset) {
  340. return this._translator.translate(value, offset)
  341. },
  342. _initAxisPositions: function() {
  343. var that = this;
  344. var position = that._options.position;
  345. that._axisPosition = that._orthogonalPositions["top" === position || "left" === position ? "start" : "end"]
  346. },
  347. _getTickMarkPoints: function(coords, length, tickOptions) {
  348. var isHorizontal = this._isHorizontal;
  349. var options = this._options;
  350. var tickStartCoord;
  351. if ((0, _type.isDefined)(options.tickOrientation)) {
  352. tickStartCoord = TICKS_CORRECTIONS[options.tickOrientation] * length
  353. } else {
  354. var shift = tickOptions.shift || 0;
  355. if ("left" === options.position || "top" === options.position) {
  356. shift = -shift
  357. }
  358. tickStartCoord = shift + this.getTickStartPositionShift(length)
  359. }
  360. return [coords.x + (isHorizontal ? 0 : tickStartCoord), coords.y + (isHorizontal ? tickStartCoord : 0), coords.x + (isHorizontal ? 0 : tickStartCoord + length), coords.y + (isHorizontal ? tickStartCoord + length : 0)]
  361. },
  362. getTickStartPositionShift: function(length) {
  363. var options = this._options;
  364. return length % 2 === 1 ? options.width % 2 === 0 && ("left" === options.position || "top" === options.position) || options.width % 2 === 1 && ("right" === options.position || "bottom" === options.position) ? Math.floor(-length / 2) : -Math.floor(length / 2) : -length / 2 + (options.width % 2 === 0 ? 0 : "bottom" === options.position || "right" === options.position ? -1 : 1)
  365. },
  366. _getTitleCoords: function() {
  367. var that = this;
  368. var horizontal = that._isHorizontal;
  369. var x = that._axisPosition;
  370. var y = that._axisPosition;
  371. var align = that._options.title.alignment;
  372. var canvas = that._getCanvasStartEnd();
  373. var fromStartToEnd = horizontal || that._options.position === LEFT;
  374. var canvasStart = fromStartToEnd ? canvas.start : canvas.end;
  375. var canvasEnd = fromStartToEnd ? canvas.end : canvas.start;
  376. var coord = align === LEFT ? canvasStart : align === RIGHT ? canvasEnd : canvas.start + (canvas.end - canvas.start) / 2;
  377. if (horizontal) {
  378. x = coord
  379. } else {
  380. y = coord
  381. }
  382. return {
  383. x: x,
  384. y: y
  385. }
  386. },
  387. _drawTitleText: function(group, coords) {
  388. var options = this._options;
  389. var titleOptions = options.title;
  390. var attrs = {
  391. opacity: titleOptions.opacity,
  392. align: titleOptions.alignment,
  393. "class": titleOptions.cssClass
  394. };
  395. if (!titleOptions.text || !group) {
  396. return
  397. }
  398. coords = coords || this._getTitleCoords();
  399. if (!this._isHorizontal) {
  400. attrs.rotate = options.position === LEFT ? 270 : 90
  401. }
  402. var text = this._renderer.text(titleOptions.text, coords.x, coords.y).css(_utils2.default.patchFontOptions(titleOptions.font)).attr(attrs).append(group);
  403. this._checkTitleOverflow(text);
  404. return text
  405. },
  406. _updateTitleCoords: function() {
  407. this._title && this._title.element.attr(this._getTitleCoords())
  408. },
  409. _drawTitle: function() {
  410. var title = this._drawTitleText(this._axisTitleGroup);
  411. if (title) {
  412. this._title = {
  413. element: title
  414. }
  415. }
  416. },
  417. _measureTitle: function() {
  418. if (this._title) {
  419. if (this._title.bBox && !this._title.originalSize) {
  420. this._title.originalSize = this._title.bBox
  421. }
  422. this._title.bBox = this._title.element.getBBox()
  423. }
  424. },
  425. _drawDateMarker: function(date, options, range) {
  426. var that = this;
  427. var markerOptions = that._options.marker;
  428. var invert = that._translator.getBusinessRange().invert;
  429. var textIndent = markerOptions.width + markerOptions.textLeftIndent;
  430. var pathElement;
  431. if (null === options.x) {
  432. return
  433. }
  434. if (!options.withoutStick) {
  435. pathElement = that._renderer.path([options.x, options.y, options.x, options.y + markerOptions.separatorHeight], "line").attr({
  436. "stroke-width": markerOptions.width,
  437. stroke: markerOptions.color,
  438. "stroke-opacity": markerOptions.opacity,
  439. sharp: "h"
  440. }).append(that._axisElementsGroup)
  441. }
  442. var text = String(that.formatLabel(date, options.labelOptions, range));
  443. return {
  444. date: date,
  445. x: options.x,
  446. y: options.y,
  447. cropped: options.withoutStick,
  448. label: that._renderer.text(text, options.x, options.y).css(_utils2.default.patchFontOptions(markerOptions.label.font)).append(that._axisElementsGroup),
  449. line: pathElement,
  450. getEnd: function() {
  451. return this.x + (invert ? -1 : 1) * (textIndent + this.labelBBox.width)
  452. },
  453. setTitle: function() {
  454. this.title = text
  455. },
  456. hideLabel: function() {
  457. this.label.dispose();
  458. this.label = null;
  459. this.title = text
  460. },
  461. hide: function() {
  462. if (pathElement) {
  463. pathElement.dispose();
  464. pathElement = null
  465. }
  466. this.label.dispose();
  467. this.label = null;
  468. this.hidden = true
  469. }
  470. }
  471. },
  472. _drawDateMarkers: function() {
  473. var that = this;
  474. var options = that._options;
  475. var translator = that._translator;
  476. var viewport = that._getViewportRange();
  477. var minBound = viewport.minVisible;
  478. var dateMarkers = [];
  479. var dateMarker;
  480. function draw(markerDate, format, withoutStick) {
  481. return that._drawDateMarker(markerDate, {
  482. x: translator.translate(markerDate),
  483. y: markersAreaTop,
  484. labelOptions: that._getLabelFormatOptions(format),
  485. withoutStick: withoutStick
  486. }, viewport)
  487. }
  488. if (viewport.isEmpty() || !options.marker.visible || "datetime" !== options.argumentType || "discrete" === options.type || that._majorTicks.length <= 1) {
  489. return []
  490. }
  491. var markersAreaTop = that._axisPosition + options.marker.topIndent;
  492. var tickInterval = _date2.default.getDateUnitInterval(this._tickInterval);
  493. var markerInterval = getMarkerInterval(tickInterval);
  494. var markerDates = getMarkerDates(minBound, viewport.maxVisible, markerInterval);
  495. if (markerDates.length > 1 || 1 === markerDates.length && minBound < markerDates[0]) {
  496. dateMarkers = markerDates.reduce(function(markers, curDate, i, dates) {
  497. var marker = draw(curDate, getMarkerFormat(curDate, dates[i - 1] || minBound < curDate && minBound, tickInterval, markerInterval));
  498. marker && markers.push(marker);
  499. return markers
  500. }, []);
  501. if (minBound < markerDates[0]) {
  502. dateMarker = draw(minBound, getMarkerFormat(minBound, markerDates[0], tickInterval, markerInterval), true);
  503. dateMarker && dateMarkers.unshift(dateMarker)
  504. }
  505. }
  506. return dateMarkers
  507. },
  508. _adjustDateMarkers: function(offset) {
  509. offset = offset || 0;
  510. var that = this;
  511. var markerOptions = this._options.marker;
  512. var textIndent = markerOptions.width + markerOptions.textLeftIndent;
  513. var invert = this._translator.getBusinessRange().invert;
  514. var canvas = that._getCanvasStartEnd();
  515. var dateMarkers = this._dateMarkers;
  516. if (!dateMarkers.length) {
  517. return offset
  518. }
  519. if (dateMarkers[0].cropped) {
  520. if (!this._checkMarkersPosition(invert, dateMarkers[1], dateMarkers[0])) {
  521. dateMarkers[0].hideLabel()
  522. }
  523. }
  524. var prevDateMarker;
  525. dateMarkers.forEach(function(marker, i, markers) {
  526. if (marker.cropped) {
  527. return
  528. }
  529. if (invert ? marker.getEnd() < canvas.end : marker.getEnd() > canvas.end) {
  530. marker.hideLabel()
  531. } else {
  532. if (that._checkMarkersPosition(invert, marker, prevDateMarker)) {
  533. prevDateMarker = marker
  534. } else {
  535. marker.hide()
  536. }
  537. }
  538. });
  539. this._dateMarkers.forEach(function(marker) {
  540. if (marker.label) {
  541. var labelBBox = marker.labelBBox;
  542. var dy = marker.y + markerOptions.textTopIndent - labelBBox.y;
  543. marker.label.attr({
  544. translateX: invert ? marker.x - textIndent - labelBBox.x - labelBBox.width : marker.x + textIndent - labelBBox.x,
  545. translateY: dy + offset
  546. })
  547. }
  548. if (marker.line) {
  549. marker.line.attr({
  550. translateY: offset
  551. })
  552. }
  553. });
  554. that._initializeMarkersTrackers(offset);
  555. return offset + markerOptions.topIndent + markerOptions.separatorHeight
  556. },
  557. _checkMarkersPosition: function(invert, dateMarker, prevDateMarker) {
  558. if (void 0 === prevDateMarker) {
  559. return true
  560. }
  561. return invert ? dateMarker.x < prevDateMarker.getEnd() : dateMarker.x > prevDateMarker.getEnd()
  562. },
  563. _initializeMarkersTrackers: function(offset) {
  564. var that = this;
  565. var separatorHeight = that._options.marker.separatorHeight;
  566. var renderer = that._renderer;
  567. var businessRange = this._translator.getBusinessRange();
  568. var canvas = that._getCanvasStartEnd();
  569. var group = that._axisElementsGroup;
  570. that._markerTrackers = this._dateMarkers.filter(function(marker) {
  571. return !marker.hidden
  572. }).map(function(marker, i, markers) {
  573. var nextMarker = markers[i + 1] || {
  574. x: canvas.end,
  575. date: businessRange.max
  576. };
  577. var x = marker.x;
  578. var y = marker.y + offset;
  579. var markerTracker = renderer.path([x, y, x, y + separatorHeight, nextMarker.x, y + separatorHeight, nextMarker.x, y, x, y], "area").attr({
  580. "stroke-width": 1,
  581. stroke: "grey",
  582. fill: "grey",
  583. opacity: 1e-4
  584. }).append(group);
  585. markerTracker.data("range", {
  586. startValue: marker.date,
  587. endValue: nextMarker.date
  588. });
  589. if (marker.title) {
  590. markerTracker.setTitle(marker.title)
  591. }
  592. return markerTracker
  593. })
  594. },
  595. _getLabelFormatOptions: function(formatString) {
  596. var that = this;
  597. var markerLabelOptions = that._markerLabelOptions;
  598. if (!markerLabelOptions) {
  599. that._markerLabelOptions = markerLabelOptions = (0, _extend.extend)(true, {}, that._options.marker.label)
  600. }
  601. if (!(0, _type.isDefined)(that._options.marker.label.format)) {
  602. markerLabelOptions.format = formatString
  603. }
  604. return markerLabelOptions
  605. },
  606. _adjustConstantLineLabels: function(constantLines) {
  607. var that = this;
  608. var axisPosition = that._options.position;
  609. var canvas = that.getCanvas();
  610. var canvasLeft = canvas.left;
  611. var canvasRight = canvas.width - canvas.right;
  612. var canvasTop = canvas.top;
  613. var canvasBottom = canvas.height - canvas.bottom;
  614. var verticalCenter = canvasTop + (canvasBottom - canvasTop) / 2;
  615. var horizontalCenter = canvasLeft + (canvasRight - canvasLeft) / 2;
  616. var maxLabel = 0;
  617. constantLines.forEach(function(item) {
  618. var isHorizontal = that._isHorizontal;
  619. var linesOptions = item.options;
  620. var paddingTopBottom = linesOptions.paddingTopBottom;
  621. var paddingLeftRight = linesOptions.paddingLeftRight;
  622. var labelOptions = linesOptions.label;
  623. var labelVerticalAlignment = labelOptions.verticalAlignment;
  624. var labelHorizontalAlignment = labelOptions.horizontalAlignment;
  625. var labelIsInside = "inside" === labelOptions.position;
  626. var label = item.label;
  627. var box = item.labelBBox;
  628. var translateX;
  629. var translateY;
  630. if (null === label || box.isEmpty) {
  631. return
  632. }
  633. if (isHorizontal) {
  634. if (labelIsInside) {
  635. if (labelHorizontalAlignment === LEFT) {
  636. translateX = item.coord - paddingLeftRight - box.x - box.width
  637. } else {
  638. translateX = item.coord + paddingLeftRight - box.x
  639. }
  640. switch (labelVerticalAlignment) {
  641. case CENTER:
  642. translateY = verticalCenter - box.y - box.height / 2;
  643. break;
  644. case BOTTOM:
  645. translateY = canvasBottom - paddingTopBottom - box.y - box.height;
  646. break;
  647. default:
  648. translateY = canvasTop + paddingTopBottom - box.y
  649. }
  650. } else {
  651. if (axisPosition === labelVerticalAlignment) {
  652. maxLabel = _max(maxLabel, box.height + paddingTopBottom)
  653. }
  654. translateX = item.coord - box.x - box.width / 2;
  655. if (labelVerticalAlignment === BOTTOM) {
  656. translateY = canvasBottom + paddingTopBottom - box.y
  657. } else {
  658. translateY = canvasTop - paddingTopBottom - box.y - box.height
  659. }
  660. }
  661. } else {
  662. if (labelIsInside) {
  663. if (labelVerticalAlignment === BOTTOM) {
  664. translateY = item.coord + paddingTopBottom - box.y
  665. } else {
  666. translateY = item.coord - paddingTopBottom - box.y - box.height
  667. }
  668. switch (labelHorizontalAlignment) {
  669. case CENTER:
  670. translateX = horizontalCenter - box.x - box.width / 2;
  671. break;
  672. case RIGHT:
  673. translateX = canvasRight - paddingLeftRight - box.x - box.width;
  674. break;
  675. default:
  676. translateX = canvasLeft + paddingLeftRight - box.x
  677. }
  678. } else {
  679. if (axisPosition === labelHorizontalAlignment) {
  680. maxLabel = _max(maxLabel, box.width + paddingLeftRight)
  681. }
  682. translateY = item.coord - box.y - box.height / 2;
  683. if (labelHorizontalAlignment === RIGHT) {
  684. translateX = canvasRight + paddingLeftRight - box.x
  685. } else {
  686. translateX = canvasLeft - paddingLeftRight - box.x - box.width
  687. }
  688. }
  689. }
  690. label.attr({
  691. translateX: translateX,
  692. translateY: translateY
  693. })
  694. });
  695. return maxLabel
  696. },
  697. _drawConstantLinesForEstimating: function(constantLines) {
  698. var that = this;
  699. var renderer = this._renderer;
  700. var group = renderer.g();
  701. constantLines.forEach(function(options) {
  702. that._drawConstantLineLabelText(options.label.text, 0, 0, options.label, group).attr({
  703. align: "center"
  704. })
  705. });
  706. return group.append(renderer.root)
  707. },
  708. _estimateLabelHeight: function(bBox, labelOptions) {
  709. var height = bBox.height;
  710. var drawingType = labelOptions.drawingType;
  711. if ("stagger" === this._validateDisplayMode(drawingType) || "stagger" === this._validateOverlappingMode(labelOptions.overlappingBehavior, drawingType)) {
  712. height = 2 * height + labelOptions.staggeringSpacing
  713. }
  714. if ("rotate" === this._validateDisplayMode(drawingType) || "rotate" === this._validateOverlappingMode(labelOptions.overlappingBehavior, drawingType)) {
  715. var sinCos = _utils2.default.getCosAndSin(labelOptions.rotationAngle);
  716. height = height * sinCos.cos + bBox.width * sinCos.sin
  717. }
  718. return height && (height + labelOptions.indentFromAxis || 0) || 0
  719. },
  720. estimateMargins: function(canvas) {
  721. this.updateCanvas(canvas);
  722. var that = this;
  723. var range = that._getViewportRange();
  724. var ticksData = this._createTicksAndLabelFormat(range);
  725. var ticks = ticksData.ticks;
  726. var tickInterval = ticksData.tickInterval;
  727. var options = this._options;
  728. var constantLineOptions = that._outsideConstantLines.filter(function(l) {
  729. return l.labelOptions.visible
  730. }).map(function(l) {
  731. return l.options
  732. });
  733. var rootElement = that._renderer.root;
  734. var labelIsVisible = options.label.visible && !range.isEmpty() && ticks.length;
  735. var labelValue = labelIsVisible && that.formatLabel(ticks[ticks.length - 1], options.label, void 0, void 0, tickInterval, ticks);
  736. var labelElement = labelIsVisible && that._renderer.text(labelValue, 0, 0).css(that._textFontStyles).attr(that._textOptions).append(rootElement);
  737. var titleElement = that._drawTitleText(rootElement, {
  738. x: 0,
  739. y: 0
  740. });
  741. var constantLinesLabelsElement = that._drawConstantLinesForEstimating(constantLineOptions);
  742. var labelBox = labelElement && labelElement.getBBox() || {
  743. x: 0,
  744. y: 0,
  745. width: 0,
  746. height: 0
  747. };
  748. var titleBox = titleElement && titleElement.getBBox() || {
  749. x: 0,
  750. y: 0,
  751. width: 0,
  752. height: 0
  753. };
  754. var constantLinesBox = constantLinesLabelsElement.getBBox();
  755. var titleHeight = titleBox.height ? titleBox.height + options.title.margin : 0;
  756. var labelHeight = that._estimateLabelHeight(labelBox, options.label);
  757. var constantLinesHeight = constantLinesBox.height ? constantLinesBox.height + getMaxConstantLinePadding(constantLineOptions) : 0;
  758. var height = labelHeight + titleHeight;
  759. var margins = {
  760. left: _max(getLeftMargin(labelBox), getLeftMargin(constantLinesBox)),
  761. right: _max(getRightMargin(labelBox), getRightMargin(constantLinesBox)),
  762. top: ("top" === options.position ? height : 0) + getConstantLineLabelMarginForVerticalAlignment(constantLineOptions, "top", constantLinesHeight),
  763. bottom: ("top" !== options.position ? height : 0) + getConstantLineLabelMarginForVerticalAlignment(constantLineOptions, "bottom", constantLinesHeight)
  764. };
  765. labelElement && labelElement.remove();
  766. titleElement && titleElement.remove();
  767. constantLinesLabelsElement && constantLinesLabelsElement.remove();
  768. return margins
  769. },
  770. _checkAlignmentConstantLineLabels: function(labelOptions) {
  771. var position = labelOptions.position;
  772. var verticalAlignment = (labelOptions.verticalAlignment || "").toLowerCase();
  773. var horizontalAlignment = (labelOptions.horizontalAlignment || "").toLowerCase();
  774. if (this._isHorizontal) {
  775. if ("outside" === position) {
  776. verticalAlignment = verticalAlignment === BOTTOM ? BOTTOM : TOP;
  777. horizontalAlignment = CENTER
  778. } else {
  779. verticalAlignment = verticalAlignment === CENTER ? CENTER : verticalAlignment === BOTTOM ? BOTTOM : TOP;
  780. horizontalAlignment = horizontalAlignment === LEFT ? LEFT : RIGHT
  781. }
  782. } else {
  783. if ("outside" === position) {
  784. verticalAlignment = CENTER;
  785. horizontalAlignment = horizontalAlignment === LEFT ? LEFT : RIGHT
  786. } else {
  787. verticalAlignment = verticalAlignment === BOTTOM ? BOTTOM : TOP;
  788. horizontalAlignment = horizontalAlignment === RIGHT ? RIGHT : horizontalAlignment === CENTER ? CENTER : LEFT
  789. }
  790. }
  791. labelOptions.verticalAlignment = verticalAlignment;
  792. labelOptions.horizontalAlignment = horizontalAlignment
  793. },
  794. _getConstantLineLabelsCoords: function(value, lineLabelOptions) {
  795. var that = this;
  796. var x = value;
  797. var y = value;
  798. if (that._isHorizontal) {
  799. y = that._orthogonalPositions["top" === lineLabelOptions.verticalAlignment ? "start" : "end"]
  800. } else {
  801. x = that._orthogonalPositions["right" === lineLabelOptions.horizontalAlignment ? "end" : "start"]
  802. }
  803. return {
  804. x: x,
  805. y: y
  806. }
  807. },
  808. _getAdjustedStripLabelCoords: function(strip) {
  809. var stripOptions = strip.options;
  810. var paddingTopBottom = stripOptions.paddingTopBottom;
  811. var paddingLeftRight = stripOptions.paddingLeftRight;
  812. var horizontalAlignment = stripOptions.label.horizontalAlignment;
  813. var verticalAlignment = stripOptions.label.verticalAlignment;
  814. var box = strip.labelBBox;
  815. var labelHeight = box.height;
  816. var labelWidth = box.width;
  817. var labelCoords = strip.labelCoords;
  818. var y = labelCoords.y - box.y;
  819. var x = labelCoords.x - box.x;
  820. if (verticalAlignment === TOP) {
  821. y += paddingTopBottom
  822. } else {
  823. if (verticalAlignment === CENTER) {
  824. y -= labelHeight / 2
  825. } else {
  826. if (verticalAlignment === BOTTOM) {
  827. y -= paddingTopBottom + labelHeight
  828. }
  829. }
  830. }
  831. if (horizontalAlignment === LEFT) {
  832. x += paddingLeftRight
  833. } else {
  834. if (horizontalAlignment === CENTER) {
  835. x -= labelWidth / 2
  836. } else {
  837. if (horizontalAlignment === RIGHT) {
  838. x -= paddingLeftRight + labelWidth
  839. }
  840. }
  841. }
  842. return {
  843. translateX: x,
  844. translateY: y
  845. }
  846. },
  847. _adjustTitle: function(offset) {
  848. offset = offset || 0;
  849. if (!this._title) {
  850. return
  851. }
  852. var that = this;
  853. var options = that._options;
  854. var position = options.position;
  855. var margin = options.title.margin;
  856. var title = that._title;
  857. var boxTitle = title.bBox;
  858. var x = boxTitle.x;
  859. var y = boxTitle.y;
  860. var width = boxTitle.width;
  861. var height = boxTitle.height;
  862. var axisPosition = that._axisPosition;
  863. var loCoord = axisPosition - margin - offset;
  864. var hiCoord = axisPosition + margin + offset;
  865. var params = {};
  866. if (that._isHorizontal) {
  867. if (position === TOP) {
  868. params.translateY = loCoord - (y + height)
  869. } else {
  870. params.translateY = hiCoord - y
  871. }
  872. } else {
  873. if (position === LEFT) {
  874. params.translateX = loCoord - (x + width)
  875. } else {
  876. params.translateX = hiCoord - x
  877. }
  878. }
  879. title.element.attr(params)
  880. },
  881. _checkTitleOverflow: function(titleElement) {
  882. if (!this._title && !titleElement) {
  883. return
  884. }
  885. var canvasLength = this._getScreenDelta();
  886. var title = titleElement ? {
  887. bBox: titleElement.getBBox(),
  888. element: titleElement
  889. } : this._title;
  890. var titleOptions = this._options.title;
  891. var boxTitle = title.bBox;
  892. if ((this._isHorizontal ? boxTitle.width : boxTitle.height) > canvasLength) {
  893. title.element.setMaxSize(canvasLength, void 0, {
  894. wordWrap: titleOptions.wordWrap || "none",
  895. textOverflow: titleOptions.textOverflow || "ellipsis"
  896. });
  897. this._wrapped = titleOptions.wordWrap && "none" !== titleOptions.wordWrap
  898. } else {
  899. var moreThanOriginalSize = title.originalSize && canvasLength > (this._isHorizontal ? title.originalSize.width : title.originalSize.height);
  900. !this._wrapped && moreThanOriginalSize && title.element.restoreText()
  901. }
  902. },
  903. coordsIn: function(x, y) {
  904. var canvas = this.getCanvas();
  905. var isHorizontal = this._options.isHorizontal;
  906. var position = this._options.position;
  907. var coord = isHorizontal ? y : x;
  908. if (isHorizontal && (x < canvas.left || x > canvas.width - canvas.right) || !isHorizontal && (y < canvas.top || y > canvas.height - canvas.bottom)) {
  909. return false
  910. }
  911. if (isHorizontal && position === _axes_constants2.default.top || !isHorizontal && position === _axes_constants2.default.left) {
  912. return coord < canvas[position]
  913. }
  914. return coord > canvas[isHorizontal ? "height" : "width"] - canvas[position]
  915. },
  916. _boundaryTicksVisibility: {
  917. min: true,
  918. max: true
  919. },
  920. _setVisualRange: function(visualRange, allowPartialUpdate) {
  921. var range = this.adjustRange(_utils2.default.getVizRangeObject(visualRange));
  922. if (allowPartialUpdate) {
  923. (0, _type.isDefined)(range.startValue) && (this._viewport.startValue = range.startValue);
  924. (0, _type.isDefined)(range.endValue) && (this._viewport.endValue = range.endValue)
  925. } else {
  926. this._viewport = range
  927. }
  928. },
  929. applyVisualRangeSetter: function(visualRangeSetter) {
  930. this._visualRange = visualRangeSetter
  931. },
  932. adjust: function(alignToBounds) {
  933. var that = this;
  934. var seriesData = that._seriesData;
  935. var viewport = {
  936. min: seriesData.min,
  937. max: seriesData.max
  938. };
  939. if (!alignToBounds) {
  940. viewport = that._series.filter(function(s) {
  941. return s.isVisible()
  942. }).reduce(function(range, s) {
  943. var seriesRange = s.getViewport();
  944. range.min = (0, _type.isDefined)(seriesRange.min) ? range.min < seriesRange.min ? range.min : seriesRange.min : range.min;
  945. range.max = (0, _type.isDefined)(seriesRange.max) ? range.max > seriesRange.max ? range.max : seriesRange.max : range.max;
  946. if (s.showZero) {
  947. range = new _range2.default.Range(range);
  948. range.correctValueZeroLevel()
  949. }
  950. return range
  951. }, {})
  952. }
  953. if ((0, _type.isDefined)(viewport.min) && (0, _type.isDefined)(viewport.max)) {
  954. seriesData.minVisible = viewport.min;
  955. seriesData.maxVisible = viewport.max
  956. }
  957. that._translator.updateBusinessRange(that.adjustViewport(seriesData));
  958. that._breaks = that._getScaleBreaks(that._options, {
  959. minVisible: seriesData.minVisible,
  960. maxVisible: seriesData.maxVisible
  961. }, that._series, that.isArgumentAxis)
  962. },
  963. hasWrap: function() {
  964. return this._wrapped
  965. },
  966. getAxisPosition: function() {
  967. return this._axisPosition
  968. },
  969. _getStick: function() {
  970. return !this._options.valueMarginsEnabled
  971. },
  972. _getStripLabelCoords: function(from, to, stripLabelOptions) {
  973. var that = this;
  974. var orthogonalPositions = that._orthogonalPositions;
  975. var isHorizontal = that._isHorizontal;
  976. var horizontalAlignment = stripLabelOptions.horizontalAlignment;
  977. var verticalAlignment = stripLabelOptions.verticalAlignment;
  978. var x;
  979. var y;
  980. if (isHorizontal) {
  981. if (horizontalAlignment === CENTER) {
  982. x = from + (to - from) / 2
  983. } else {
  984. if (horizontalAlignment === LEFT) {
  985. x = from
  986. } else {
  987. if (horizontalAlignment === RIGHT) {
  988. x = to
  989. }
  990. }
  991. }
  992. y = orthogonalPositions[getStripVerticalAlignmentPosition(verticalAlignment)]
  993. } else {
  994. x = orthogonalPositions[getStripHorizontalAlignmentPosition(horizontalAlignment)];
  995. if (verticalAlignment === TOP) {
  996. y = from
  997. } else {
  998. if (verticalAlignment === CENTER) {
  999. y = to + (from - to) / 2
  1000. } else {
  1001. if (verticalAlignment === BOTTOM) {
  1002. y = to
  1003. }
  1004. }
  1005. }
  1006. }
  1007. return {
  1008. x: x,
  1009. y: y
  1010. }
  1011. },
  1012. _getTranslatedValue: function(value, offset) {
  1013. var pos1 = this._translator.translate(value, offset, "semidiscrete" === this._options.type && this._options.tickInterval);
  1014. var pos2 = this._axisPosition;
  1015. var isHorizontal = this._isHorizontal;
  1016. return {
  1017. x: isHorizontal ? pos1 : pos2,
  1018. y: isHorizontal ? pos2 : pos1
  1019. }
  1020. },
  1021. areCoordsOutsideAxis: function(coords) {
  1022. var coord = this._isHorizontal ? coords.x : coords.y;
  1023. var visibleArea = this.getVisibleArea();
  1024. if (coord < visibleArea[0] || coord > visibleArea[1]) {
  1025. return true
  1026. }
  1027. return false
  1028. },
  1029. _getSkippedCategory: function(ticks) {
  1030. var skippedCategory;
  1031. if (this._options.type === _axes_constants2.default.discrete && this._tickOffset && 0 !== ticks.length) {
  1032. skippedCategory = ticks[ticks.length - 1]
  1033. }
  1034. return skippedCategory
  1035. },
  1036. _getScaleBreaks: function(axisOptions, viewport, series, isArgumentAxis) {
  1037. var that = this;
  1038. var breaks = (axisOptions.breaks || []).map(function(b) {
  1039. return {
  1040. from: that.parser(b.startValue),
  1041. to: that.parser(b.endValue)
  1042. }
  1043. });
  1044. if ("discrete" !== axisOptions.type && "datetime" === axisOptions.dataType && axisOptions.workdaysOnly) {
  1045. breaks = breaks.concat((0, _datetime_breaks.generateDateBreaks)(viewport.minVisible, viewport.maxVisible, axisOptions.workWeek, axisOptions.singleWorkdays, axisOptions.holidays))
  1046. }
  1047. if (!isArgumentAxis && "discrete" !== axisOptions.type && "datetime" !== axisOptions.dataType && axisOptions.autoBreaksEnabled && 0 !== axisOptions.maxAutoBreakCount) {
  1048. breaks = breaks.concat(generateAutoBreaks(axisOptions, series, viewport))
  1049. }
  1050. return filterBreaks(sortingBreaks(breaks), viewport, axisOptions.breakStyle)
  1051. },
  1052. _drawBreak: function(translatedEnd, positionFrom, positionTo, width, options, group) {
  1053. var that = this;
  1054. var breakStart = translatedEnd - (!that._translator.isInverted() ? width + 1 : 0);
  1055. var attr = {
  1056. "stroke-width": 1,
  1057. stroke: options.borderColor,
  1058. sharp: !options.isWaved ? options.isHorizontal ? "h" : "v" : void 0
  1059. };
  1060. var spaceAttr = {
  1061. stroke: options.color,
  1062. "stroke-width": width
  1063. };
  1064. var getPoints = that._isHorizontal ? rotateLine : function(p) {
  1065. return p
  1066. };
  1067. var drawer = getLineDrawer(that._renderer, group, getPoints, positionFrom, breakStart, positionTo, options.isWaved);
  1068. drawer(width / 2, spaceAttr);
  1069. drawer(0, attr);
  1070. drawer(width, attr)
  1071. },
  1072. _createBreakClipRect: function(from, to) {
  1073. var that = this;
  1074. var canvas = that._canvas;
  1075. var clipWidth = to - from;
  1076. var clipRect;
  1077. if (that._isHorizontal) {
  1078. clipRect = that._renderer.clipRect(canvas.left, from, canvas.width, clipWidth)
  1079. } else {
  1080. clipRect = that._renderer.clipRect(from, canvas.top, clipWidth, canvas.height)
  1081. }
  1082. that._breaksElements = that._breaksElements || [];
  1083. that._breaksElements.push(clipRect);
  1084. return clipRect.id
  1085. },
  1086. _createBreaksGroup: function(clipFrom, clipTo) {
  1087. var that = this;
  1088. var group = that._renderer.g().attr({
  1089. "class": that._axisCssPrefix + "breaks",
  1090. "clip-path": that._createBreakClipRect(clipFrom, clipTo)
  1091. }).append(that._scaleBreaksGroup);
  1092. that._breaksElements = that._breaksElements || [];
  1093. that._breaksElements.push(group);
  1094. return group
  1095. },
  1096. _disposeBreaksGroup: function() {
  1097. (this._breaksElements || []).forEach(function(clipRect) {
  1098. clipRect.dispose()
  1099. });
  1100. this._breaksElements = null
  1101. },
  1102. drawScaleBreaks: function(customCanvas) {
  1103. var that = this;
  1104. var options = that._options;
  1105. var breakStyle = options.breakStyle;
  1106. var position = options.position;
  1107. var positionFrom;
  1108. var positionTo;
  1109. var breaks = that._translator.getBusinessRange().breaks || [];
  1110. var additionGroup;
  1111. var additionBreakFrom;
  1112. var additionBreakTo;
  1113. that._disposeBreaksGroup();
  1114. if (!(breaks && breaks.length)) {
  1115. return
  1116. }
  1117. var breakOptions = {
  1118. color: that._options.containerColor,
  1119. borderColor: breakStyle.color,
  1120. isHorizontal: that._isHorizontal,
  1121. isWaved: "straight" !== breakStyle.line.toLowerCase()
  1122. };
  1123. if (customCanvas) {
  1124. positionFrom = customCanvas.start;
  1125. positionTo = customCanvas.end
  1126. } else {
  1127. positionFrom = that._orthogonalPositions.start - (options.visible && !that._axisShift && ("left" === position || "top" === position) ? SCALE_BREAK_OFFSET : 0);
  1128. positionTo = that._orthogonalPositions.end + (options.visible && ("right" === position || "bottom" === position) ? SCALE_BREAK_OFFSET : 0)
  1129. }
  1130. var mainGroup = that._createBreaksGroup(positionFrom, positionTo);
  1131. if (that._axisShift && options.visible) {
  1132. additionBreakFrom = that._axisPosition - that._axisShift - SCALE_BREAK_OFFSET;
  1133. additionBreakTo = additionBreakFrom + 2 * SCALE_BREAK_OFFSET;
  1134. additionGroup = that._createBreaksGroup(additionBreakFrom, additionBreakTo)
  1135. }
  1136. breaks.forEach(function(br) {
  1137. if (!br.gapSize) {
  1138. var breakCoord = that._getTranslatedCoord(br.to);
  1139. that._drawBreak(breakCoord, positionFrom, positionTo, breakStyle.width, breakOptions, mainGroup);
  1140. if (that._axisShift && options.visible) {
  1141. that._drawBreak(breakCoord, additionBreakFrom, additionBreakTo, breakStyle.width, breakOptions, additionGroup)
  1142. }
  1143. }
  1144. })
  1145. },
  1146. _getSpiderCategoryOption: _common.noop,
  1147. shift: function(margins) {
  1148. var that = this;
  1149. var options = that._options;
  1150. var isHorizontal = options.isHorizontal;
  1151. var axesSpacing = that.getMultipleAxesSpacing();
  1152. var constantLinesGroups = that._axisConstantLineGroups;
  1153. function shiftGroup(side, group) {
  1154. var attr = {
  1155. translateX: 0,
  1156. translateY: 0
  1157. };
  1158. var shift = margins[side] ? margins[side] + axesSpacing : 0;
  1159. attr[isHorizontal ? "translateY" : "translateX"] = ("left" === side || "top" === side ? -1 : 1) * shift;
  1160. (group[side] || group).attr(attr);
  1161. return shift
  1162. }
  1163. that._axisShift = shiftGroup(options.position, that._axisGroup);
  1164. (isHorizontal ? ["top", "bottom"] : ["left", "right"]).forEach(function(side) {
  1165. shiftGroup(side, constantLinesGroups.above);
  1166. shiftGroup(side, constantLinesGroups.under)
  1167. })
  1168. }
  1169. }
  1170. };
  1171. function getLineDrawer(renderer, root, rotatePoints, positionFrom, breakStart, positionTo, isWaved) {
  1172. var elementType = isWaved ? "bezier" : "line";
  1173. var group = renderer.g().append(root);
  1174. return function(offset, attr) {
  1175. renderer.path(rotatePoints(getPoints(positionFrom, breakStart, positionTo, offset, isWaved)), elementType).attr(attr).append(group)
  1176. }
  1177. }
  1178. function getPoints(positionFrom, breakStart, positionTo, offset, isWaved) {
  1179. if (!isWaved) {
  1180. return [positionFrom, breakStart + offset, positionTo, breakStart + offset]
  1181. }
  1182. breakStart += offset;
  1183. var currentPosition;
  1184. var topPoint = breakStart + WAVED_LINE_TOP;
  1185. var centerPoint = breakStart + WAVED_LINE_CENTER;
  1186. var bottomPoint = breakStart + WAVED_LINE_BOTTOM;
  1187. var points = [
  1188. [positionFrom, centerPoint]
  1189. ];
  1190. for (currentPosition = positionFrom; currentPosition < positionTo + WAVED_LINE_LENGTH; currentPosition += WAVED_LINE_LENGTH) {
  1191. points.push([currentPosition + 6, topPoint, currentPosition + 6, topPoint, currentPosition + 12, centerPoint, currentPosition + 18, bottomPoint, currentPosition + 18, bottomPoint, currentPosition + 24, centerPoint])
  1192. }
  1193. return [].concat.apply([], points)
  1194. }
  1195. function rotateLine(lineCoords) {
  1196. var points = [];
  1197. var i;
  1198. for (i = 0; i < lineCoords.length; i += 2) {
  1199. points.push(lineCoords[i + 1]);
  1200. points.push(lineCoords[i])
  1201. }
  1202. return points
  1203. }