@devexperts/dxcharts-lite 2.2.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dist/chart/bootstrap.js +4 -3
  2. package/dist/chart/canvas/canvas-bounds-container.d.ts +2 -2
  3. package/dist/chart/canvas/canvas-bounds-container.js +7 -5
  4. package/dist/chart/canvas/cursor.handler.js +2 -2
  5. package/dist/chart/chart.config.d.ts +17 -4
  6. package/dist/chart/chart.config.js +6 -2
  7. package/dist/chart/components/chart/chart-area-pan.handler.js +13 -8
  8. package/dist/chart/components/chart/chart.component.d.ts +6 -3
  9. package/dist/chart/components/chart/chart.component.js +18 -7
  10. package/dist/chart/components/chart/chart.model.d.ts +1 -2
  11. package/dist/chart/components/chart/chart.model.js +2 -3
  12. package/dist/chart/components/cross_tool/cross-tool.model.js +1 -1
  13. package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.js +4 -2
  14. package/dist/chart/components/high_low/high-low.drawer.js +9 -2
  15. package/dist/chart/components/highlights/highlights.drawer.js +1 -1
  16. package/dist/chart/components/pane/pane.component.js +6 -3
  17. package/dist/chart/components/snapshot/snapshot.component.js +1 -0
  18. package/dist/chart/components/volumes/separate-volumes.component.js +2 -1
  19. package/dist/chart/components/volumes/volumes.drawer.js +1 -1
  20. package/dist/chart/components/volumes/volumes.formatter.d.ts +1 -1
  21. package/dist/chart/components/volumes/volumes.formatter.js +28 -25
  22. package/dist/chart/components/x_axis/time/parser/time-formats-matchers.functions.js +1 -1
  23. package/dist/chart/components/x_axis/time/parser/time-formats.model.d.ts +1 -1
  24. package/dist/chart/components/x_axis/time/x-axis-weights.functions.js +2 -2
  25. package/dist/chart/components/x_axis/time/x-axis-weights.generator.js +6 -7
  26. package/dist/chart/components/x_axis/x-axis-labels.generator.d.ts +11 -3
  27. package/dist/chart/components/x_axis/x-axis-labels.generator.js +47 -19
  28. package/dist/chart/components/x_axis/x-axis-time-labels.drawer.js +0 -4
  29. package/dist/chart/components/x_axis/x-axis.component.js +7 -11
  30. package/dist/chart/components/y_axis/price_labels/last-candle-labels.provider.js +5 -5
  31. package/dist/chart/components/y_axis/price_labels/price-label.drawer.js +21 -22
  32. package/dist/chart/components/y_axis/y-axis-labels.drawer.d.ts +18 -6
  33. package/dist/chart/components/y_axis/y-axis-labels.drawer.js +23 -12
  34. package/dist/chart/components/y_axis/y-axis-scale.handler.d.ts +9 -4
  35. package/dist/chart/components/y_axis/y-axis-scale.handler.js +22 -15
  36. package/dist/chart/components/y_axis/y-axis.component.js +1 -0
  37. package/dist/chart/components/y_axis/y-axis.drawer.js +1 -1
  38. package/dist/chart/drawers/chart-background.drawer.d.ts +2 -3
  39. package/dist/chart/drawers/chart-background.drawer.js +16 -22
  40. package/dist/chart/drawers/data-series-drawers/candle-series-wrapper.js +1 -1
  41. package/dist/chart/drawers/data-series.drawer.d.ts +0 -2
  42. package/dist/chart/drawers/data-series.drawer.js +2 -7
  43. package/dist/chart/drawers/ht-data-series.drawer.js +1 -1
  44. package/dist/chart/inputhandlers/hover-producer.component.d.ts +1 -1
  45. package/dist/chart/inputlisteners/canvas-input-listener.component.d.ts +9 -0
  46. package/dist/chart/inputlisteners/canvas-input-listener.component.js +38 -1
  47. package/dist/chart/model/compare-series-hover.d.ts +1 -1
  48. package/dist/chart/model/compare-series-hover.js +5 -0
  49. package/dist/chart/model/data-series.model.js +1 -1
  50. package/dist/chart/model/hit-test-canvas.model.js +2 -2
  51. package/dist/chart/model/scale.model.d.ts +6 -3
  52. package/dist/chart/model/scale.model.js +46 -9
  53. package/dist/chart/model/scaling/constrait.functions.d.ts +1 -1
  54. package/dist/chart/model/scaling/constrait.functions.js +1 -2
  55. package/dist/chart/model/scaling/lock-ratio.model.d.ts +8 -2
  56. package/dist/chart/model/scaling/lock-ratio.model.js +18 -3
  57. package/dist/chart/model/scaling/viewport.model.d.ts +2 -0
  58. package/dist/chart/model/scaling/viewport.model.js +13 -4
  59. package/dist/chart/model/time-zone.model.d.ts +0 -14
  60. package/dist/chart/model/time-zone.model.js +13 -33
  61. package/dist/chart/utils/canvas/canvas-drawing-functions.utils.d.ts +12 -1
  62. package/dist/chart/utils/canvas/canvas-drawing-functions.utils.js +16 -1
  63. package/dist/chart/utils/canvas/canvas-text-functions.utils.d.ts +3 -2
  64. package/dist/chart/utils/canvas/canvas-text-functions.utils.js +8 -3
  65. package/dist/chart/utils/device/touchpad.utils.d.ts +3 -3
  66. package/dist/chart/utils/device/touchpad.utils.js +3 -5
  67. package/dist/chart/utils/math.utils.d.ts +1 -1
  68. package/dist/chart/utils/math.utils.js +4 -1
  69. package/dist/chart/utils/timezone.utils.d.ts +13 -0
  70. package/dist/chart/utils/timezone.utils.js +48 -0
  71. package/dist/dxchart.min.js +6 -6
  72. package/package.json +1 -2
@@ -18,12 +18,10 @@ import { getWeightFromTimeFormat } from './x-axis-weights.functions';
18
18
  * @see
19
19
  * returns `null` if date doesn't match any condition
20
20
  */
21
- const getWeightByDate = (currentDate, previousDate, sortedWeights, tzOffset) => {
21
+ const getWeightByDate = (currentDate, previousDate, sortedWeights) => {
22
22
  var _a, _b;
23
- const offsetCurrentDate = tzOffset(currentDate.getTime());
24
- const offsetPrevDate = tzOffset(previousDate.getTime());
25
23
  for (const [weight, timeMatcher] of sortedWeights) {
26
- if (timeMatcher(offsetCurrentDate, offsetPrevDate)) {
24
+ if (timeMatcher(currentDate, previousDate)) {
27
25
  return weight;
28
26
  }
29
27
  }
@@ -36,12 +34,13 @@ const getWeightByDate = (currentDate, previousDate, sortedWeights, tzOffset) =>
36
34
  export function mapCandlesToWeightedPoints(visualCandles, sortedWeights, tzOffset) {
37
35
  const result = new Array(visualCandles.length);
38
36
  // assume that candles` timestamp before the first visual candle is unreachable
39
- let prevDate = new Date(0);
37
+ let prevDate = tzOffset(0);
40
38
  for (let i = 0; i < visualCandles.length; i++) {
41
39
  const currentCandle = visualCandles[i];
42
- const currentDate = new Date(currentCandle.candle.timestamp);
40
+ // calculate timstamp to Date in acordance with provided timezone and time
41
+ const currentDate = tzOffset(currentCandle.candle.timestamp);
43
42
  const currentWeightedPoint = {
44
- weight: getWeightByDate(currentDate, prevDate, sortedWeights, tzOffset),
43
+ weight: getWeightByDate(currentDate, prevDate, sortedWeights),
45
44
  };
46
45
  result[i] = currentWeightedPoint;
47
46
  prevDate = currentDate;
@@ -3,6 +3,7 @@
3
3
  * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4
4
  * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
+ import { CanvasBoundsContainer } from '../../canvas/canvas-bounds-container';
6
7
  import { FullChartConfig } from '../../chart.config';
7
8
  import EventBus from '../../events/event-bus';
8
9
  import { CanvasModel } from '../../model/canvas.model';
@@ -48,6 +49,7 @@ export declare class XAxisTimeLabelsGenerator implements XAxisLabelsGenerator {
48
49
  private scale;
49
50
  private timeZoneModel;
50
51
  private canvasModel;
52
+ private canvasBoundsContainer;
51
53
  private labelsGroupedByWeight;
52
54
  private weightedCache?;
53
55
  private levelsCache;
@@ -56,7 +58,8 @@ export declare class XAxisTimeLabelsGenerator implements XAxisLabelsGenerator {
56
58
  private weightToTimeFormatMatcherArray;
57
59
  private weightToTimeFormatsDict;
58
60
  private extendedLabelsFilterConfig;
59
- constructor(eventBus: EventBus, config: FullChartConfig, chartModel: ChartModel, scale: ScaleModel, timeZoneModel: TimeZoneModel, canvasModel: CanvasModel);
61
+ constructor(eventBus: EventBus, config: FullChartConfig, chartModel: ChartModel, scale: ScaleModel, timeZoneModel: TimeZoneModel, canvasModel: CanvasModel, canvasBoundsContainer: CanvasBoundsContainer);
62
+ private filterLabelsInViewport;
60
63
  private getLabelsFromChartType;
61
64
  /**
62
65
  * Make a prediction(750) about how many candles we need to fake to fill all X axis by labels
@@ -110,11 +113,16 @@ export declare class XAxisTimeLabelsGenerator implements XAxisLabelsGenerator {
110
113
  * @returns {void}
111
114
  */
112
115
  recalculateLabels(): void;
116
+ /**
117
+ * Calculates the cover up level based on the maximum label width and the mean candle width.
118
+ * Cover up level is based on maximum label width, which is based on the font size and the maximum format length.
119
+ * Used to group labels.
120
+ */
121
+ private calculateCoverUpLevel;
113
122
  /**
114
123
  * Recalculates cached labels based on the current configuration and zoom level.
115
124
  * If there are no grouped labels, the cache is not set.
116
- * Calculates the maximum label width based on the font size and the maximum format length.
117
- * Calculates the cover up level based on the maximum label width and the mean candle width.
125
+ * Recalculating depends on cover up level.
118
126
  * If the cover up level is negative, the cache is not updated.
119
127
  * If the cover up level has not changed, the cached labels are returned.
120
128
  * Otherwise, the labels are filtered by extended rules and grouped by cover up level.
@@ -3,6 +3,7 @@
3
3
  * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4
4
  * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
+ import { CanvasElement } from '../../canvas/canvas-bounds-container';
6
7
  import { unitToPixels } from '../../model/scaling/viewport.model';
7
8
  import { cloneUnsafe, typedEntries_UNSAFE } from '../../utils/object.utils';
8
9
  import { fakeVisualCandle } from '../chart/fake-candles';
@@ -11,15 +12,16 @@ import { filterMapGroupedLabelsByCoverUpLevel, getWeightFromTimeFormat, groupLab
11
12
  import { generateWeightsMapForConfig, mapCandlesToWeightedPoints, } from './time/x-axis-weights.generator';
12
13
  export class XAxisTimeLabelsGenerator {
13
14
  get labels() {
14
- return this.getLabelsFromChartType();
15
+ return this.filterLabelsInViewport(this.getLabelsFromChartType());
15
16
  }
16
- constructor(eventBus, config, chartModel, scale, timeZoneModel, canvasModel) {
17
+ constructor(eventBus, config, chartModel, scale, timeZoneModel, canvasModel, canvasBoundsContainer) {
17
18
  this.eventBus = eventBus;
18
19
  this.config = config;
19
20
  this.chartModel = chartModel;
20
21
  this.scale = scale;
21
22
  this.timeZoneModel = timeZoneModel;
22
23
  this.canvasModel = canvasModel;
24
+ this.canvasBoundsContainer = canvasBoundsContainer;
23
25
  this.labelsGroupedByWeight = {};
24
26
  this.levelsCache = {};
25
27
  this.weightToTimeFormatMatcherArray = [];
@@ -27,6 +29,29 @@ export class XAxisTimeLabelsGenerator {
27
29
  this.extendedLabelsFilterConfig = {
28
30
  minute_1: (coverUpLevel) => coverUpLevel >= 2,
29
31
  };
32
+ /**
33
+ * Calculates the cover up level based on the maximum label width and the mean candle width.
34
+ * Cover up level is based on maximum label width, which is based on the font size and the maximum format length.
35
+ * Used to group labels.
36
+ */
37
+ this.calculateCoverUpLevel = () => {
38
+ const animation = this.scale.currentAnimation;
39
+ const meanCandleWidthInUnits = this.chartModel.mainCandleSeries.meanCandleWidth;
40
+ if (Object.getOwnPropertyNames(this.labelsGroupedByWeight).length === 0) {
41
+ return -1;
42
+ }
43
+ // calculate coverUpLevel for target zoomX to prevent extra labels calculations on every animation tick
44
+ const meanCandleWidthInPixels = (animation === null || animation === void 0 ? void 0 : animation.animationInProgress)
45
+ ? unitToPixels(meanCandleWidthInUnits, animation.animationConfig.targetZoomX)
46
+ : unitToPixels(meanCandleWidthInUnits, this.scale.zoomX);
47
+ if (!isFinite(meanCandleWidthInPixels)) {
48
+ return -1;
49
+ }
50
+ const fontSize = this.config.components.xAxis.fontSize;
51
+ const maxFormatLength = Object.values(this.formatsByWeightMap).reduce((max, item) => Math.max(item.length, max), 1);
52
+ const maxLabelWidth = fontSize * maxFormatLength;
53
+ return Math.round(maxLabelWidth / meanCandleWidthInPixels);
54
+ };
30
55
  this.formatsByWeightMap = config.components.xAxis.formatsForLabelsConfig;
31
56
  const { weightToTimeFormatsDict, weightToTimeFormatMatcherDict } = generateWeightsMapForConfig(this.formatsByWeightMap);
32
57
  this.weightToTimeFormatMatcherArray = Object.entries(weightToTimeFormatMatcherDict)
@@ -34,6 +59,19 @@ export class XAxisTimeLabelsGenerator {
34
59
  .sort(([a], [b]) => b - a);
35
60
  this.weightToTimeFormatsDict = weightToTimeFormatsDict;
36
61
  }
62
+ filterLabelsInViewport(labels) {
63
+ const bounds = this.canvasBoundsContainer.getBounds(CanvasElement.X_AXIS);
64
+ const filteredLabels = [];
65
+ for (const label of labels) {
66
+ const x = this.scale.toX(label.value);
67
+ // skip labels outside viewport
68
+ if (x < 0 || x > bounds.width) {
69
+ continue;
70
+ }
71
+ filteredLabels.push(label);
72
+ }
73
+ return filteredLabels;
74
+ }
37
75
  getLabelsFromChartType() {
38
76
  var _a, _b;
39
77
  const labels = (_b = (_a = this.weightedCache) === null || _a === void 0 ? void 0 : _a.labels) !== null && _b !== void 0 ? _b : [];
@@ -64,9 +102,10 @@ export class XAxisTimeLabelsGenerator {
64
102
  * @returns {XAxisLabelWeighted[]} An array of XAxisLabelWeighted objects.
65
103
  */
66
104
  mapWeightedPointsToLabels(weightedPoints, allCandlesWithFake) {
105
+ var _a;
67
106
  const arr = new Array(weightedPoints.length);
68
- weightedPoints.forEach((point, index) => {
69
- var _a;
107
+ for (let index = 0; index < weightedPoints.length; ++index) {
108
+ const point = weightedPoints[index];
70
109
  const visualCandle = allCandlesWithFake[index];
71
110
  const labelFormat = this.weightToTimeFormatsDict[point.weight];
72
111
  const formattedLabel = this.timeZoneModel.getDateTimeFormatter(labelFormat)(visualCandle.candle.timestamp);
@@ -77,7 +116,7 @@ export class XAxisTimeLabelsGenerator {
77
116
  time: visualCandle.candle.timestamp,
78
117
  text: formattedLabel,
79
118
  };
80
- });
119
+ }
81
120
  return arr;
82
121
  }
83
122
  /**
@@ -227,27 +266,16 @@ export class XAxisTimeLabelsGenerator {
227
266
  /**
228
267
  * Recalculates cached labels based on the current configuration and zoom level.
229
268
  * If there are no grouped labels, the cache is not set.
230
- * Calculates the maximum label width based on the font size and the maximum format length.
231
- * Calculates the cover up level based on the maximum label width and the mean candle width.
269
+ * Recalculating depends on cover up level.
232
270
  * If the cover up level is negative, the cache is not updated.
233
271
  * If the cover up level has not changed, the cached labels are returned.
234
272
  * Otherwise, the labels are filtered by extended rules and grouped by cover up level.
235
273
  * The filtered labels are then cached and returned.
236
274
  */
237
275
  recalculateCachedLabels() {
238
- // skip cache setting if we don't have grouped labels
239
- if (Object.getOwnPropertyNames(this.labelsGroupedByWeight).length === 0) {
240
- return;
241
- }
242
- const fontSize = this.config.components.xAxis.fontSize;
243
- const maxFormatLength = Object.values(this.formatsByWeightMap).reduce((max, item) => {
244
- return Math.max(item.length, max);
245
- }, 1);
246
- const maxLabelWidth = fontSize * maxFormatLength;
247
- const meanCandleWidthPx = unitToPixels(this.chartModel.mainCandleSeries.meanCandleWidth, this.scale.zoomX);
248
- const coverUpLevel = Math.round(maxLabelWidth / meanCandleWidthPx);
276
+ const coverUpLevel = this.calculateCoverUpLevel();
249
277
  // for some reason sometimes `this.scale.zoomX` is negative so we dont want to update labels
250
- if (coverUpLevel < 0 && !isFinite(meanCandleWidthPx)) {
278
+ if (coverUpLevel < 0) {
251
279
  return;
252
280
  }
253
281
  if (this.weightedCache === undefined || coverUpLevel !== this.weightedCache.coverUpLevel) {
@@ -58,10 +58,6 @@ export class XAxisTimeLabelsDrawer {
58
58
  ctx.fillStyle = color;
59
59
  for (const label of labels) {
60
60
  const x = this.viewportModel.toX(label.value) - calculateTextWidth(label.text, ctx, font) / 2;
61
- // skip labels outside viewport
62
- if (x < 0 || x > bounds.width) {
63
- continue;
64
- }
65
61
  const y = bounds.y + fontHeight - 1 + offsetTop; // -1 for font drawing inconsistency
66
62
  const labelText = label.text;
67
63
  ctx.font = font;
@@ -3,7 +3,7 @@
3
3
  * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4
4
  * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
- import { merge } from 'rxjs';
6
+ import { merge, animationFrameScheduler } from 'rxjs';
7
7
  import { distinctUntilChanged, map, throttleTime, filter } from 'rxjs/operators';
8
8
  import { CanvasElement } from '../../canvas/canvas-bounds-container';
9
9
  import { ChartBaseElement } from '../../model/chart-base-element';
@@ -29,7 +29,7 @@ export class XAxisComponent extends ChartBaseElement {
29
29
  this.scale = scale;
30
30
  this.chartResizeHandler = chartResizeHandler;
31
31
  this.timeZoneModel = timeZoneModel;
32
- const xAxisLabelsGenerator = new XAxisTimeLabelsGenerator(eventBus, config, chartComponent.chartModel, scale, timeZoneModel, this.canvasModel);
32
+ const xAxisLabelsGenerator = new XAxisTimeLabelsGenerator(eventBus, config, chartComponent.chartModel, scale, timeZoneModel, this.canvasModel, canvasBoundsContainer);
33
33
  this.xAxisLabelsGenerator = xAxisLabelsGenerator;
34
34
  this.xAxisLabelsModel = new XAxisLabelsModel(eventBus, []);
35
35
  const xAxisCompositeDrawer = new CompositeDrawer();
@@ -56,26 +56,22 @@ export class XAxisComponent extends ChartBaseElement {
56
56
  this.xAxisLabelsGenerator.generateLabels();
57
57
  }));
58
58
  this.addRxSubscription(this.chartComponent.chartModel.candlesPrependSubject
59
- .pipe(filter(({ prependedCandles }) => prependedCandles.length !== 0), map(({ prependedCandles }) => {
60
- return this.chartComponent.chartModel.mainCandleSeries.visualPoints.slice(0, prependedCandles.length);
61
- }))
59
+ .pipe(filter(({ prependedCandles }) => prependedCandles.length !== 0), map(({ prependedCandles }) => this.chartComponent.chartModel.mainCandleSeries.visualPoints.slice(0, prependedCandles.length)))
62
60
  .subscribe(newCandles => {
61
+ var _a, _b;
63
62
  //@ts-ignore
64
63
  if (availableBarTypes.includes(this.config.components.chart.type)) {
65
- this.xAxisLabelsGenerator.updateHistoryLabels &&
66
- this.xAxisLabelsGenerator.updateHistoryLabels(newCandles);
64
+ (_b = (_a = this.xAxisLabelsGenerator).updateHistoryLabels) === null || _b === void 0 ? void 0 : _b.call(_a, newCandles);
67
65
  }
68
66
  }));
69
67
  this.addRxSubscription(merge(this.scale.xChanged, this.chartResizeHandler.canvasResized)
70
- .pipe(throttleTime(50, undefined, { trailing: true, leading: true }))
68
+ .pipe(throttleTime(50, animationFrameScheduler, { trailing: true, leading: true }))
71
69
  .subscribe(() => {
72
70
  this.xAxisLabelsGenerator.recalculateLabels();
73
71
  }));
74
72
  this.addRxSubscription(this.chartComponent.chartModel.candlesUpdatedSubject
75
73
  .pipe(map(() => lastOf(this.chartComponent.chartModel.mainCandleSeries.visualPoints)), distinctUntilChanged((a, b) => { var _a, _b; return ((_a = a === null || a === void 0 ? void 0 : a.candle) === null || _a === void 0 ? void 0 : _a.timestamp) === ((_b = b === null || b === void 0 ? void 0 : b.candle) === null || _b === void 0 ? void 0 : _b.timestamp); }), filter(notEmpty))
76
- .subscribe(x => {
77
- this.xAxisLabelsGenerator.updateLastLabel && this.xAxisLabelsGenerator.updateLastLabel(x);
78
- }));
74
+ .subscribe(x => { var _a, _b; return (_b = (_a = this.xAxisLabelsGenerator) === null || _a === void 0 ? void 0 : _a.updateLastLabel) === null || _b === void 0 ? void 0 : _b.call(_a, x); }));
79
75
  }
80
76
  /**
81
77
  * Returns the xAxisDrawer object.
@@ -3,7 +3,7 @@
3
3
  * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
4
4
  * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
- import { getPlainLabelTextColor, getPrimaryLabelTextColor } from '../label-color.functions';
6
+ import { getPrimaryLabelTextColor } from '../label-color.functions';
7
7
  import { lastOf } from '../../../utils/array.utils';
8
8
  import { getLabelTextColorByBackgroundColor } from '../../../utils/canvas/canvas-text-functions.utils';
9
9
  export class LastCandleLabelsProvider {
@@ -87,7 +87,7 @@ export class LastCandleLabelsProvider {
87
87
  const appearanceType = this.yAxisConfig.labels.settings.lastPrice.type;
88
88
  const colors = series.colors.labels;
89
89
  const { rectLabelTextColor = 'white', rectLabelInvertedTextColor = 'black' } = this.chartConfig.colors.yAxis;
90
- const getLabelBoxColor = this.resolveLabelColorFn(series.config.type);
90
+ const getLabelColorBySeries = this.resolveLabelColorFn(series.config.type);
91
91
  if (!colors) {
92
92
  return {
93
93
  bgColor: '#FFFFFF',
@@ -95,14 +95,14 @@ export class LastCandleLabelsProvider {
95
95
  rounded: true,
96
96
  };
97
97
  }
98
- const boxColor = getLabelBoxColor(series.lastPriceMovement, series.colors);
98
+ const boxColor = getLabelColorBySeries(series.lastPriceMovement, series.colors);
99
99
  // if the label is for the main candle series
100
100
  if (primary) {
101
101
  const textColor = getPrimaryLabelTextColor(series.lastPriceMovement, colors);
102
102
  return {
103
103
  bgColor: boxColor,
104
104
  textColor: appearanceType === 'plain'
105
- ? getPlainLabelTextColor(this.chartConfig.colors, textColor, rectLabelInvertedTextColor, this.yAxisConfig)
105
+ ? getLabelColorBySeries(series.lastPriceMovement, series.colors)
106
106
  : getLabelTextColorByBackgroundColor(boxColor, textColor, rectLabelInvertedTextColor),
107
107
  rounded: true,
108
108
  };
@@ -111,7 +111,7 @@ export class LastCandleLabelsProvider {
111
111
  return {
112
112
  bgColor: boxColor,
113
113
  textColor: appearanceType === 'plain'
114
- ? getPlainLabelTextColor(this.chartConfig.colors, rectLabelTextColor, rectLabelInvertedTextColor, this.yAxisConfig)
114
+ ? getLabelColorBySeries(series.lastPriceMovement, series.colors)
115
115
  : getLabelTextColorByBackgroundColor(boxColor, rectLabelTextColor, rectLabelInvertedTextColor),
116
116
  rounded: true,
117
117
  };
@@ -9,7 +9,7 @@ import { redrawBackgroundArea } from '../../../drawers/chart-background.drawer';
9
9
  import { avoidAntialiasing, drawLine } from '../../../utils/canvas/canvas-drawing-functions.utils';
10
10
  import { calculateSymbolHeight, calculateTextWidth } from '../../../utils/canvas/canvas-font-measure-tool.utils';
11
11
  import { floor } from '../../../utils/math.utils';
12
- import { drawBadgeLabel, drawPlainLabel, drawRectLabel } from '../y-axis-labels.drawer';
12
+ import { drawBadgeLabel, drawPlainLabel, drawRectLabel, checkLabelInBoundaries } from '../y-axis-labels.drawer';
13
13
  export const DEFAULT_LABEL_APPEARANCE_TYPE = 'badge';
14
14
  const DEFAULT_PADDING = 4;
15
15
  export const priceLabelDrawersMap = {
@@ -66,22 +66,26 @@ export function drawLabel(ctx, backgroundCtx, bounds, paneBounds, visualLabel, c
66
66
  const lineY = (_e = visualLabel.lineY) !== null && _e !== void 0 ? _e : visualLabel.y;
67
67
  const _drawLine = () => showLine && avoidAntialiasing(ctx, () => drawLine(ctx, lineXStart, lineY, lineXEnd, lineY, 1));
68
68
  const _drawLabel = () => drawLabel(ctx, bounds, text, centralY, visualLabel, config, colors, false, backgroundCtx);
69
- switch (mode) {
70
- case 'line':
71
- _drawLine();
72
- _drawDescription();
73
- break;
74
- case 'line-label':
75
- _drawLine();
76
- _drawDescription();
77
- _drawLabel();
78
- break;
79
- case 'label':
80
- _drawDescription();
81
- _drawLabel();
82
- break;
83
- case 'none':
84
- break;
69
+ const drawLineLabel = () => {
70
+ _drawLine();
71
+ _drawDescription();
72
+ };
73
+ const drawLineLabelLabel = () => {
74
+ _drawLine();
75
+ _drawLabel();
76
+ _drawDescription();
77
+ };
78
+ const drawLabelLabel = () => {
79
+ _drawDescription();
80
+ _drawLabel();
81
+ };
82
+ const labelDrawerByMode = {
83
+ 'line': drawLineLabel,
84
+ 'line-label': drawLineLabelLabel,
85
+ 'label': drawLabelLabel,
86
+ };
87
+ if (mode !== 'none' && checkLabelInBoundaries(centralY, bounds, labelBoxHeight)) {
88
+ labelDrawerByMode[mode]();
85
89
  }
86
90
  ctx.restore();
87
91
  }
@@ -101,11 +105,6 @@ function drawDescription(backgroundCtx, ctx, labelBounds, paneBounds, visualLabe
101
105
  const labelBoxY = centralY - fontHeight / 2 - paddingTop;
102
106
  const labelBoxBottom = centralY + fontHeight / 2 + paddingBottom;
103
107
  const labelBoxHeight = labelBoxBottom - labelBoxY;
104
- // do not draw, if description is out of bounds
105
- if (centralY < labelBounds.y + labelBoxHeight / 2 ||
106
- centralY > labelBounds.y + labelBounds.height - labelBoxHeight / 2) {
107
- return;
108
- }
109
108
  ctx.save();
110
109
  // overlay rect
111
110
  const width = descriptionWidth + 5;
@@ -34,10 +34,11 @@ export declare const DEFAULT_PRICE_LABEL_PADDING = 4;
34
34
  * @param text - text to draw
35
35
  * @param centralY - y
36
36
  * @param config - label styles config
37
- * @param align
38
37
  * @param yAxisState
38
+ * @param yAxisColors
39
+ * @param checkBoundaries
39
40
  */
40
- export declare function drawBadgeLabel(ctx: CanvasRenderingContext2D, bounds: Bounds, text: string, centralY: number, config: YAxisLabelDrawConfig, yAxisState: YAxisConfig, yAxisColors: FullChartColors['yAxis'], drawOutside?: boolean): void;
41
+ export declare function drawBadgeLabel(ctx: CanvasRenderingContext2D, bounds: Bounds, text: string, centralY: number, config: YAxisLabelDrawConfig, yAxisState: YAxisConfig, yAxisColors: FullChartColors['yAxis'], checkBoundaries?: boolean): void;
41
42
  /**
42
43
  * Draws rectangle label on Y axis with provided parameters.
43
44
  * @param ctx - canvas 2D context to draw on
@@ -45,10 +46,11 @@ export declare function drawBadgeLabel(ctx: CanvasRenderingContext2D, bounds: Bo
45
46
  * @param text - text to draw
46
47
  * @param centralY - y
47
48
  * @param config - label styles config
48
- * @param align
49
49
  * @param yAxisState
50
+ * @param yAxisColors
51
+ * @param checkBoundaries
50
52
  */
51
- export declare function drawRectLabel(ctx: CanvasRenderingContext2D, bounds: Bounds, text: string, centralY: number, config: YAxisLabelDrawConfig, yAxisState: YAxisConfig, yAxisColors: FullChartColors['yAxis'], drawOutside?: boolean): void;
53
+ export declare function drawRectLabel(ctx: CanvasRenderingContext2D, bounds: Bounds, text: string, centralY: number, config: YAxisLabelDrawConfig, yAxisState: YAxisConfig, yAxisColors: FullChartColors['yAxis'], checkBoundaries?: boolean): void;
52
54
  /**
53
55
  * Draws rectangle label on Y axis with provided parameters but with transparent background.
54
56
  * @param ctx - canvas 2D context to draw on
@@ -56,10 +58,12 @@ export declare function drawRectLabel(ctx: CanvasRenderingContext2D, bounds: Bou
56
58
  * @param text - text to draw
57
59
  * @param centralY - y
58
60
  * @param config - label styles config
59
- * @param align
60
61
  * @param yAxisState
62
+ * @param yAxisColors
63
+ * @param checkBoundaries
64
+ * @param backgroundCtx
61
65
  */
62
- export declare function drawPlainLabel(ctx: CanvasRenderingContext2D, bounds: Bounds, text: string, centralY: number, config: YAxisLabelDrawConfig, yAxisState: YAxisConfig, yAxisColors: FullChartColors['yAxis'], drawOutside?: boolean, backgroundCtx?: CanvasRenderingContext2D): void;
66
+ export declare function drawPlainLabel(ctx: CanvasRenderingContext2D, bounds: Bounds, text: string, centralY: number, config: YAxisLabelDrawConfig, yAxisState: YAxisConfig, yAxisColors: FullChartColors['yAxis'], checkBoundaries?: boolean, backgroundCtx?: CanvasRenderingContext2D): void;
63
67
  /**
64
68
  * Offset from the center of label to the top/bottom.
65
69
  *
@@ -68,3 +72,11 @@ export declare function drawPlainLabel(ctx: CanvasRenderingContext2D, bounds: Bo
68
72
  * @param paddingTop - extra padding from top
69
73
  */
70
74
  export declare function getLabelYOffset(font: string, ctx: CanvasRenderingContext2D, paddingTop?: number): number;
75
+ /**
76
+ * Checks if label fits in chart scale boundaries
77
+ * @param centralY
78
+ * @param bounds
79
+ * @param labelBoxHeight
80
+ * returns true if label fits
81
+ */
82
+ export declare function checkLabelInBoundaries(centralY: number, bounds: Bounds, labelBoxHeight: number): boolean;
@@ -17,10 +17,11 @@ export const DEFAULT_PRICE_LABEL_PADDING = 4;
17
17
  * @param text - text to draw
18
18
  * @param centralY - y
19
19
  * @param config - label styles config
20
- * @param align
21
20
  * @param yAxisState
21
+ * @param yAxisColors
22
+ * @param checkBoundaries
22
23
  */
23
- export function drawBadgeLabel(ctx, bounds, text, centralY, config, yAxisState, yAxisColors, drawOutside = false) {
24
+ export function drawBadgeLabel(ctx, bounds, text, centralY, config, yAxisState, yAxisColors, checkBoundaries = true) {
24
25
  var _a, _b, _c, _d, _e, _f, _g;
25
26
  const align = yAxisState.align;
26
27
  const textFont = (_a = config.textFont) !== null && _a !== void 0 ? _a : getFontFromConfig(yAxisState);
@@ -34,8 +35,7 @@ export function drawBadgeLabel(ctx, bounds, text, centralY, config, yAxisState,
34
35
  const labelBoxBottomY = centralY + halfFontHeight + paddingBottom;
35
36
  const labelBoxHeight = labelBoxBottomY - labelBoxTopY;
36
37
  // do not draw, if label is out of bounds
37
- if ((centralY < bounds.y + labelBoxHeight / 2 || centralY > bounds.y + bounds.height - labelBoxHeight / 2) &&
38
- !drawOutside) {
38
+ if (checkBoundaries && !checkLabelInBoundaries(centralY, bounds, labelBoxHeight)) {
39
39
  return;
40
40
  }
41
41
  ctx.save();
@@ -64,10 +64,11 @@ export function drawBadgeLabel(ctx, bounds, text, centralY, config, yAxisState,
64
64
  * @param text - text to draw
65
65
  * @param centralY - y
66
66
  * @param config - label styles config
67
- * @param align
68
67
  * @param yAxisState
68
+ * @param yAxisColors
69
+ * @param checkBoundaries
69
70
  */
70
- export function drawRectLabel(ctx, bounds, text, centralY, config, yAxisState, yAxisColors, drawOutside = false) {
71
+ export function drawRectLabel(ctx, bounds, text, centralY, config, yAxisState, yAxisColors, checkBoundaries = true) {
71
72
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
72
73
  const align = yAxisState.align;
73
74
  const textFont = (_a = config.textFont) !== null && _a !== void 0 ? _a : getFontFromConfig(yAxisState);
@@ -84,8 +85,7 @@ export function drawRectLabel(ctx, bounds, text, centralY, config, yAxisState, y
84
85
  const labelBoxHeight = labelBoxBottomY - labelBoxTopY;
85
86
  const rounded = (_k = config.rounded) !== null && _k !== void 0 ? _k : (_l = yAxisState.typeConfig.rectangle) === null || _l === void 0 ? void 0 : _l.rounded;
86
87
  // do not draw, if label is out of bounds
87
- if ((centralY < bounds.y + labelBoxHeight / 2 || centralY > bounds.y + bounds.height - labelBoxHeight / 2) &&
88
- !drawOutside) {
88
+ if (checkBoundaries && !checkLabelInBoundaries(centralY, bounds, labelBoxHeight)) {
89
89
  return;
90
90
  }
91
91
  ctx.save();
@@ -115,10 +115,12 @@ export function drawRectLabel(ctx, bounds, text, centralY, config, yAxisState, y
115
115
  * @param text - text to draw
116
116
  * @param centralY - y
117
117
  * @param config - label styles config
118
- * @param align
119
118
  * @param yAxisState
119
+ * @param yAxisColors
120
+ * @param checkBoundaries
121
+ * @param backgroundCtx
120
122
  */
121
- export function drawPlainLabel(ctx, bounds, text, centralY, config, yAxisState, yAxisColors, drawOutside = false, backgroundCtx) {
123
+ export function drawPlainLabel(ctx, bounds, text, centralY, config, yAxisState, yAxisColors, checkBoundaries = true, backgroundCtx) {
122
124
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
123
125
  const align = yAxisState.align;
124
126
  const textFont = (_a = config.textFont) !== null && _a !== void 0 ? _a : getFontFromConfig(yAxisState);
@@ -134,8 +136,7 @@ export function drawPlainLabel(ctx, bounds, text, centralY, config, yAxisState,
134
136
  const labelBoxBottomY = centralY + fontHeight / 2 + paddingBottom;
135
137
  const labelBoxHeight = labelBoxBottomY - labelBoxTopY;
136
138
  // do not draw, if label is out of bounds
137
- if ((centralY < bounds.y + labelBoxHeight / 2 || centralY > bounds.y + bounds.height - labelBoxHeight / 2) &&
138
- !drawOutside) {
139
+ if (checkBoundaries && !checkLabelInBoundaries(centralY, bounds, labelBoxHeight)) {
139
140
  return;
140
141
  }
141
142
  ctx.save();
@@ -164,3 +165,13 @@ export function getLabelYOffset(font, ctx, paddingTop = DEFAULT_PRICE_LABEL_PADD
164
165
  const fontHeight = calculateSymbolHeight(font, ctx);
165
166
  return fontHeight / 2 + paddingTop;
166
167
  }
168
+ /**
169
+ * Checks if label fits in chart scale boundaries
170
+ * @param centralY
171
+ * @param bounds
172
+ * @param labelBoxHeight
173
+ * returns true if label fits
174
+ */
175
+ export function checkLabelInBoundaries(centralY, bounds, labelBoxHeight) {
176
+ return !(centralY < bounds.y + labelBoxHeight / 2 || centralY > bounds.y + bounds.height - labelBoxHeight / 2);
177
+ }
@@ -9,23 +9,28 @@ import { YAxisConfig } from '../../chart.config';
9
9
  import EventBus from '../../events/event-bus';
10
10
  import { ChartBaseElement } from '../../model/chart-base-element';
11
11
  import { CanvasInputListenerComponent } from '../../inputlisteners/canvas-input-listener.component';
12
- import { Pixel, Unit, ViewportModel } from '../../model/scaling/viewport.model';
12
+ import { Pixel, Unit } from '../../model/scaling/viewport.model';
13
13
  import { ChartPanComponent } from '../pan/chart-pan.component';
14
+ import { ScaleModel } from '../../model/scale.model';
14
15
  /**
15
16
  * Handles the mouse drag on Y axis - to zoom the viewport vertically.
16
17
  * @doc-tags scaling,zoom,viewport
17
18
  */
18
19
  export declare class YAxisScaleHandler extends ChartBaseElement {
19
20
  private bus;
20
- private viewportModel;
21
- private canvasBoundsContainer;
21
+ private config;
22
+ private scale;
23
+ private canvasInputListener;
24
+ private bounds;
25
+ private hitTest;
22
26
  private autoScaleCallback;
23
27
  yAxisDragEndSubject: Subject<void>;
24
28
  lastYStart: Unit;
25
29
  lastYEnd: Unit;
26
30
  lastYHeight: Unit;
27
31
  lastYPxHeight: Pixel;
28
- constructor(bus: EventBus, config: YAxisConfig, chartPanComponent: ChartPanComponent, viewportModel: ViewportModel, canvasInputListener: CanvasInputListenerComponent, canvasBoundsContainer: CanvasBoundsContainer, hitTest: HitBoundsTest, autoScaleCallback: (auto: boolean) => void);
32
+ constructor(bus: EventBus, config: YAxisConfig, panning: ChartPanComponent, scale: ScaleModel, canvasInputListener: CanvasInputListenerComponent, bounds: CanvasBoundsContainer, hitTest: HitBoundsTest, autoScaleCallback: (auto: boolean) => void);
33
+ protected doActivate(): void;
29
34
  private onYDragStart;
30
35
  private onYDragTick;
31
36
  private onYDragEnd;
@@ -14,11 +14,14 @@ const FULL_Y_HEIGHT_ZOOM_FACTOR = 10;
14
14
  * @doc-tags scaling,zoom,viewport
15
15
  */
16
16
  export class YAxisScaleHandler extends ChartBaseElement {
17
- constructor(bus, config, chartPanComponent, viewportModel, canvasInputListener, canvasBoundsContainer, hitTest, autoScaleCallback) {
17
+ constructor(bus, config, panning, scale, canvasInputListener, bounds, hitTest, autoScaleCallback) {
18
18
  super();
19
19
  this.bus = bus;
20
- this.viewportModel = viewportModel;
21
- this.canvasBoundsContainer = canvasBoundsContainer;
20
+ this.config = config;
21
+ this.scale = scale;
22
+ this.canvasInputListener = canvasInputListener;
23
+ this.bounds = bounds;
24
+ this.hitTest = hitTest;
22
25
  this.autoScaleCallback = autoScaleCallback;
23
26
  this.yAxisDragEndSubject = new Subject();
24
27
  this.lastYStart = 0;
@@ -26,10 +29,12 @@ export class YAxisScaleHandler extends ChartBaseElement {
26
29
  this.lastYHeight = 0;
27
30
  this.lastYPxHeight = 0;
28
31
  this.onYDragStart = () => {
29
- this.lastYStart = this.viewportModel.yStart;
30
- this.lastYEnd = this.viewportModel.yEnd;
31
- this.lastYHeight = this.viewportModel.yEnd - this.viewportModel.yStart;
32
- this.lastYPxHeight = this.canvasBoundsContainer.getBounds(CanvasElement.Y_AXIS).height;
32
+ // halt previous scale animation if drag is started
33
+ this.scale.haltAnimation();
34
+ this.lastYStart = this.scale.yStart;
35
+ this.lastYEnd = this.scale.yEnd;
36
+ this.lastYHeight = this.scale.yEnd - this.scale.yStart;
37
+ this.lastYPxHeight = this.bounds.getBounds(CanvasElement.Y_AXIS).height;
33
38
  };
34
39
  this.onYDragTick = (dragInfo) => {
35
40
  const { delta: absoluteYDelta } = dragInfo;
@@ -48,7 +53,7 @@ export class YAxisScaleHandler extends ChartBaseElement {
48
53
  const newYStart = this.lastYStart - delta;
49
54
  const newYEnd = this.lastYEnd + delta;
50
55
  this.autoScaleCallback(false);
51
- this.viewportModel.setYScale(newYStart, newYEnd);
56
+ this.scale.setYScale(newYStart, newYEnd);
52
57
  this.bus.fireDraw();
53
58
  };
54
59
  this.onYDragEnd = () => {
@@ -61,16 +66,18 @@ export class YAxisScaleHandler extends ChartBaseElement {
61
66
  onDragTick: callIfPredicateTrue(this.onYDragTick, dragPredicate),
62
67
  onDragStart: callIfPredicateTrue(this.onYDragStart, dragPredicate),
63
68
  onDragEnd: callIfPredicateTrue(this.onYDragEnd, dragPredicate),
64
- }, canvasInputListener, chartPanComponent, {
69
+ }, canvasInputListener, panning, {
65
70
  disableChartPanning: false,
66
71
  });
67
72
  this.addChildEntity(dragNDropYComponent);
68
- if (config.customScaleDblClick) {
69
- canvasInputListener.observeDbClick(hitTest).subscribe(() => {
70
- autoScaleCallback(true);
71
- this.bus.fireDraw();
72
- });
73
- }
73
+ }
74
+ }
75
+ doActivate() {
76
+ if (this.config.customScaleDblClick) {
77
+ this.addRxSubscription(this.canvasInputListener.observeDbClick(this.hitTest).subscribe(() => {
78
+ this.autoScaleCallback(true);
79
+ this.bus.fireDraw();
80
+ }));
74
81
  }
75
82
  }
76
83
  }
@@ -151,6 +151,7 @@ export class YAxisComponent extends ChartBaseElement {
151
151
  setAxisType(type) {
152
152
  if (type !== this.state.type) {
153
153
  this.state.type = type;
154
+ this.config.components.yAxis.type = type;
154
155
  this.axisTypeSetSubject.next(type);
155
156
  this.scale.autoScale(true);
156
157
  this.model.fancyLabelsModel.updateLabels(true);
@@ -4,7 +4,7 @@
4
4
  * If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
  */
6
6
  import { getFontFromConfig } from '../../chart.config';
7
- import { clipToBounds } from '../../drawers/data-series.drawer';
7
+ import { clipToBounds } from '../../utils/canvas/canvas-drawing-functions.utils';
8
8
  import { calculateSymbolHeight, calculateTextWidth } from '../../utils/canvas/canvas-font-measure-tool.utils';
9
9
  /**
10
10
  * Draws the Y_AXIS rectangle + it's base labels.