@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
@@ -106,8 +106,9 @@ export default class ChartBootstrap {
106
106
  // canvas animation container
107
107
  const canvasAnimation = new CanvasAnimation(eventBus);
108
108
  this.canvasAnimation = canvasAnimation;
109
+ const chartPaneId = CanvasElement.PANE_UUID(CHART_UUID);
109
110
  //#region ScaleModel init
110
- const scaleModel = new ScaleModel(config, () => canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(CHART_UUID)), canvasAnimation);
111
+ const scaleModel = new ScaleModel(config, () => canvasBoundsContainer.getBounds(chartPaneId), canvasAnimation);
111
112
  this.scaleModel = scaleModel;
112
113
  //#endregion
113
114
  const backgroundCanvasModel = createCanvasModel(eventBus, elements.backgroundCanvas, config, drawingManager, this.canvasModels, elements.chartResizer, {
@@ -135,7 +136,7 @@ export default class ChartBootstrap {
135
136
  this.chartComponents.push(this.dynamicObjects);
136
137
  this.chartModel = new ChartModel(chartBaseModel, paneManager, eventBus, this.dynamicObjectsCanvasModel, config, scaleModel, formatterFactory, mainCanvasParent, canvasBoundsContainer, chartResizeHandler);
137
138
  //#region main chart component init
138
- const chartComponent = new ChartComponent(this.chartModel, this.dynamicObjectsCanvasModel, config, scaleModel, canvasBoundsContainer, drawingManager, hitTestCanvasModel, canvasInputListener, backgroundCanvasModel, chartPanComponent, paneManager, this.cursorHandler, this.dynamicObjects);
139
+ const chartComponent = new ChartComponent(this.chartModel, this.dynamicObjectsCanvasModel, config, scaleModel, canvasBoundsContainer, drawingManager, hitTestCanvasModel, canvasInputListener, backgroundCanvasModel, chartPanComponent, paneManager, this.cursorHandler, this.dynamicObjects, this.chartResizeHandler);
139
140
  this.chartComponents.push(chartComponent);
140
141
  this.chartComponent = chartComponent;
141
142
  const chartModel = this.chartComponent.chartModel;
@@ -175,7 +176,7 @@ export default class ChartBootstrap {
175
176
  this.volumesComponent = new VolumesComponent(this.dynamicObjectsCanvasModel, chartComponent, scaleModel, canvasBoundsContainer, drawingManager, config, paneManager, this.dynamicObjects);
176
177
  this.chartComponents.push(this.volumesComponent);
177
178
  // grid component
178
- const mainChartGridComponent = new GridComponent(mainCanvasModel, scaleModel, config, this.yAxisComponent.state, 'GRID', drawingManager, () => this.canvasBoundsContainer.getBounds(CanvasElement.ALL_PANES), () => this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(CHART_UUID)), () => this.xAxisComponent.xAxisLabelsGenerator.labels, () => this.yAxisComponent.model.baseLabelsModel.labels, () => mainPane.mainExtent.toY(mainPane.mainExtent.getBaseline()), () => config.components.grid.visible);
179
+ const mainChartGridComponent = new GridComponent(mainCanvasModel, scaleModel, config, this.yAxisComponent.state, 'GRID', drawingManager, () => this.canvasBoundsContainer.getBounds(CanvasElement.ALL_PANES), () => this.canvasBoundsContainer.getBounds(chartPaneId), () => this.xAxisComponent.xAxisLabelsGenerator.labels, () => this.yAxisComponent.model.baseLabelsModel.labels, () => mainPane.mainExtent.toY(mainPane.mainExtent.getBaseline()), () => config.components.grid.visible);
179
180
  this.chartComponents.push(mainChartGridComponent);
180
181
  this.hoverProducer = new HoverProducerComponent(this.crossEventProducer, scaleModel, config, chartModel, canvasInputListener, this.canvasBoundsContainer, this.paneManager, timeZoneModel, formatterFactory);
181
182
  this.chartComponents.push(this.hoverProducer);
@@ -35,11 +35,11 @@ export declare class CanvasElement {
35
35
  static CHART_WITH_Y_AXIS: string;
36
36
  static EVENTS: string;
37
37
  /**
38
- * @deprecated - use CanvasElement.PANE_UUID(CHART_UUID) instead
38
+ * @returns pane bounds for the main chart
39
39
  */
40
40
  static CHART: string;
41
41
  /**
42
- * @deprecated - use CanvasElement.PANE_UUID_Y_AXIS(CHART_UUID) instead
42
+ * @returns y-axis bounds for the main chart
43
43
  */
44
44
  static Y_AXIS: string;
45
45
  }
@@ -31,11 +31,11 @@ CanvasElement.ALL_PANES = 'ALL_PANES';
31
31
  CanvasElement.CHART_WITH_Y_AXIS = 'CHART_WITH_Y_AXIS';
32
32
  CanvasElement.EVENTS = 'EVENTS';
33
33
  /**
34
- * @deprecated - use CanvasElement.PANE_UUID(CHART_UUID) instead
34
+ * @returns pane bounds for the main chart
35
35
  */
36
36
  CanvasElement.CHART = CanvasElement.PANE_UUID(CHART_UUID);
37
37
  /**
38
- * @deprecated - use CanvasElement.PANE_UUID_Y_AXIS(CHART_UUID) instead
38
+ * @returns y-axis bounds for the main chart
39
39
  */
40
40
  CanvasElement.Y_AXIS = CanvasElement.PANE_UUID_Y_AXIS(CHART_UUID);
41
41
  export { CanvasElement };
@@ -565,10 +565,12 @@ export class CanvasBoundsContainer {
565
565
  * @return {Bounds} bounds of element
566
566
  */
567
567
  getBounds(el) {
568
- if (this.bounds[el] === undefined) {
569
- this.bounds[el] = this.copyOf(DEFAULT_BOUNDS);
568
+ let bounds = this.bounds[el];
569
+ if (bounds === undefined) {
570
+ bounds = this.copyOf(DEFAULT_BOUNDS);
571
+ this.bounds[el] = bounds;
570
572
  }
571
- return this.bounds[el];
573
+ return bounds;
572
574
  }
573
575
  /**
574
576
  * Returns the position of CANVAS on whole page.
@@ -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 { Subject } from 'rxjs';
6
+ import { Subject, animationFrameScheduler } from 'rxjs';
7
7
  import { distinctUntilChanged, throttleTime } from 'rxjs/operators';
8
8
  import { ChartBaseElement } from '../model/chart-base-element';
9
9
  import { CanvasBoundsContainer } from './canvas-bounds-container';
@@ -29,7 +29,7 @@ export class CursorHandler extends ChartBaseElement {
29
29
  super.doActivate();
30
30
  this.canvasInputListener
31
31
  .observeMouseMoveNoDrag()
32
- .pipe(throttleTime(100, undefined, { trailing: true }))
32
+ .pipe(throttleTime(100, animationFrameScheduler, { trailing: true }))
33
33
  .subscribe(point => {
34
34
  const cursorFromHT = this.hitTestCanvasModel.resolveCursor(point);
35
35
  if (cursorFromHT !== undefined) {
@@ -233,10 +233,23 @@ export interface ChartScale {
233
233
  * When dragging chart under specific angle - will automatically disable auto-scale.
234
234
  */
235
235
  autoScaleDisableOnDrag: AutoScaleDisableOnDrag;
236
- /**
237
- * 0..1 ratio of full viewport; 0.5 = middle, 0.75 = 3/4 of viewport
238
- */
239
- zoomSensitivity: number;
236
+ zoomSensitivity: {
237
+ /**
238
+ * Value is related to zoom event (zooming chart via mouse wheel)
239
+ * 0..1 ratio of full viewport; 0.5 = middle, 0.75 = 3/4 of viewport
240
+ */
241
+ wheel: number;
242
+ /**
243
+ * Value is related to pinch touchpad event (zooming chart via touchpad)
244
+ * 0..1 ratio of full viewport; 0.5 = middle, 0.75 = 3/4 of viewport
245
+ */
246
+ pinch: number;
247
+ /**
248
+ * Value is related to glide touchpad event (scrolling chart via touchpad)
249
+ * 0..1 ratio of full viewport; 0.5 = middle, 0.75 = 3/4 of viewport
250
+ */
251
+ glide: number;
252
+ };
240
253
  /**
241
254
  * Defines how much items (candles) will be in viewport when chart applies basic scale
242
255
  */
@@ -41,9 +41,13 @@ export const getDefaultConfig = () => ({
41
41
  yDiff: 80,
42
42
  },
43
43
  inverse: false,
44
- zoomSensitivity: 0.25,
44
+ zoomSensitivity: {
45
+ wheel: 0.25,
46
+ pinch: 0.05,
47
+ glide: 0.05,
48
+ },
45
49
  defaultViewportItems: 100,
46
- disableAnimations: false
50
+ disableAnimations: false,
47
51
  },
48
52
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
49
53
  components: {
@@ -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 { throttleTime } from 'rxjs/operators';
8
8
  import { VIEWPORT_ANIMATION_ID } from '../../animation/canvas-animation';
9
9
  import { CanvasElement } from '../../canvas/canvas-bounds-container';
@@ -60,10 +60,8 @@ export class ChartAreaPanHandler extends ChartBaseElement {
60
60
  * @param {WheelEvent} e - Wheel event
61
61
  * @returns {void}
62
62
  */
63
- this.zoomXHandler = (e) => {
64
- const isTouchpad = touchpadDetector(e);
63
+ this.zoomXHandler = (e, zoomSensitivity) => {
65
64
  const zoomIn = e.deltaY < 0;
66
- const zoomSensitivity = isTouchpad ? getTouchpadSensitivity(this.config) : this.config.scale.zoomSensitivity;
67
65
  if (this.config.scale.zoomToCursor) {
68
66
  const b = this.canvasBoundsContainer.getBounds(CanvasElement.CANVAS);
69
67
  const canvasW = b.width;
@@ -114,11 +112,17 @@ export class ChartAreaPanHandler extends ChartBaseElement {
114
112
  const allPanesHitTest = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.ALL_PANES);
115
113
  //#endregion
116
114
  this.addRxSubscription(merge(this.canvasInputListener.observeWheel(allPanesHitTest), this.canvasInputListener.observePinch(allPanesHitTest))
117
- .pipe(throttleTime(this.wheelTrottleTime, undefined, { trailing: true, leading: true }))
118
- .subscribe(this.zoomXHandler));
115
+ .pipe(throttleTime(this.wheelTrottleTime, animationFrameScheduler, { trailing: true, leading: true }))
116
+ .subscribe(e => {
117
+ const isTouchpad = touchpadDetector(e);
118
+ const zoomSensitivity = isTouchpad
119
+ ? getTouchpadSensitivity(this.config.components.yAxis.type, this.config.scale.zoomSensitivity.pinch)
120
+ : this.config.scale.zoomSensitivity.wheel;
121
+ this.zoomXHandler(e, zoomSensitivity);
122
+ }));
119
123
  this.addRxSubscription(this.canvasInputListener
120
124
  .observeScrollGesture()
121
- .pipe(throttleTime(this.wheelTrottleTime, undefined, { trailing: true, leading: true }))
125
+ .pipe(throttleTime(this.wheelTrottleTime, animationFrameScheduler, { trailing: true, leading: true }))
122
126
  .subscribe((e) => {
123
127
  let direction = -1;
124
128
  const device = deviceDetector();
@@ -134,7 +138,8 @@ export class ChartAreaPanHandler extends ChartBaseElement {
134
138
  this.scale.moveXStart(this.scale.xStart - unitsDelta);
135
139
  }
136
140
  else if (deltaY !== 0 && Math.abs(deltaY) > Math.abs(deltaX)) {
137
- this.zoomXHandler(e);
141
+ const zoomSensitivity = getTouchpadSensitivity(this.config.components.yAxis.type, this.config.scale.zoomSensitivity.glide);
142
+ this.zoomXHandler(e, zoomSensitivity);
138
143
  }
139
144
  this.bus.fireDraw();
140
145
  }));
@@ -24,6 +24,7 @@ import { PaneManager } from '../pane/pane-manager.component';
24
24
  import { CandleWidthCalculator, ChartModel, LastCandleLabelHandler, VisualCandleCalculator } from './chart.model';
25
25
  import { PrependedCandlesData } from './chart-base.model';
26
26
  import { DynamicObjectsComponent } from '../dynamic-objects/dynamic-objects.component';
27
+ import { ChartResizeHandler } from '../../inputhandlers/chart-resize.handler';
27
28
  /**
28
29
  * Represents a financial instrument to be displayed on a chart
29
30
  * @class
@@ -59,11 +60,13 @@ export declare class ChartComponent extends ChartBaseElement {
59
60
  private canvasInputListener;
60
61
  private paneManager;
61
62
  private dynamicObjects;
63
+ private chartResizeHandler;
62
64
  readonly baselineModel: BaselineModel;
63
65
  private readonly backgroundDrawer;
64
66
  private readonly _dataSeriesDrawers;
65
67
  private readonly dataSeriesDrawer;
66
- constructor(chartModel: ChartModel, canvasModel: CanvasModel, config: FullChartConfig, scale: ScaleModel, canvasBoundsContainer: CanvasBoundsContainer, drawingManager: DrawingManager, hitTestCanvasModel: HitTestCanvasModel, canvasInputListener: CanvasInputListenerComponent, backgroundCanvasModel: CanvasModel, chartPanComponent: ChartPanComponent, paneManager: PaneManager, cursorHandler: CursorHandler, dynamicObjects: DynamicObjectsComponent);
68
+ private backgroundDrawPredicateSubj;
69
+ constructor(chartModel: ChartModel, canvasModel: CanvasModel, config: FullChartConfig, scale: ScaleModel, canvasBoundsContainer: CanvasBoundsContainer, drawingManager: DrawingManager, hitTestCanvasModel: HitTestCanvasModel, canvasInputListener: CanvasInputListenerComponent, backgroundCanvasModel: CanvasModel, chartPanComponent: ChartPanComponent, paneManager: PaneManager, cursorHandler: CursorHandler, dynamicObjects: DynamicObjectsComponent, chartResizeHandler: ChartResizeHandler);
67
70
  /**
68
71
  * This method overrides the doActivate method of the parent class and calls it.
69
72
  * It does not take any parameters and does not return anything.
@@ -118,13 +121,13 @@ export declare class ChartComponent extends ChartBaseElement {
118
121
  * @param {Timestamp} end - The end timestamp of the range.
119
122
  * @returns {void}
120
123
  */
121
- setTimestampRange(start: Timestamp, end: Timestamp): void;
124
+ setTimestampRange(start: Timestamp, end: Timestamp, forceNoAnimation?: boolean): void;
122
125
  /**
123
126
  * Moves the viewport to exactly xStart..xEnd place.
124
127
  * @param xStart - viewport start in units
125
128
  * @param xEnd - viewport end in units
126
129
  */
127
- setXScale(xStart: Unit, xEnd: Unit): void;
130
+ setXScale(xStart: Unit, xEnd: Unit, forceNoAnimation?: boolean): void;
128
131
  /**
129
132
  * Sets the visibility of the wicks in the chart.
130
133
  * @param {boolean} isShow - A boolean value indicating whether to show or hide the wicks.
@@ -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 { BehaviorSubject } from 'rxjs';
6
7
  import { CHART_UUID, CanvasElement } from '../../canvas/canvas-bounds-container';
7
8
  import { ChartBaseElement } from '../../model/chart-base-element';
8
9
  import { BackgroundDrawer } from '../../drawers/chart-background.drawer';
@@ -48,7 +49,7 @@ export class ChartInstrument {
48
49
  }
49
50
  }
50
51
  export class ChartComponent extends ChartBaseElement {
51
- constructor(chartModel, canvasModel, config, scale, canvasBoundsContainer, drawingManager, hitTestCanvasModel, canvasInputListener, backgroundCanvasModel, chartPanComponent, paneManager, cursorHandler, dynamicObjects) {
52
+ constructor(chartModel, canvasModel, config, scale, canvasBoundsContainer, drawingManager, hitTestCanvasModel, canvasInputListener, backgroundCanvasModel, chartPanComponent, paneManager, cursorHandler, dynamicObjects, chartResizeHandler) {
52
53
  super();
53
54
  this.chartModel = chartModel;
54
55
  this.canvasModel = canvasModel;
@@ -60,7 +61,9 @@ export class ChartComponent extends ChartBaseElement {
60
61
  this.canvasInputListener = canvasInputListener;
61
62
  this.paneManager = paneManager;
62
63
  this.dynamicObjects = dynamicObjects;
64
+ this.chartResizeHandler = chartResizeHandler;
63
65
  this._dataSeriesDrawers = {};
66
+ this.backgroundDrawPredicateSubj = new BehaviorSubject(true);
64
67
  this.strToBarType = (str) => { var _a; return (_a = this.barTypeValues.find(t => t === str)) !== null && _a !== void 0 ? _a : 'candle'; };
65
68
  this.addChildEntity(this.chartModel);
66
69
  this.registerDefaultCandlesTransformers();
@@ -73,7 +76,7 @@ export class ChartComponent extends ChartBaseElement {
73
76
  //#region data series drawers
74
77
  this.registerDefaultDataSeriesDrawers();
75
78
  //#endregion
76
- this.backgroundDrawer = new BackgroundDrawer(backgroundCanvasModel, this.config);
79
+ this.backgroundDrawer = new BackgroundDrawer(backgroundCanvasModel, this.config, () => this.backgroundDrawPredicateSubj.getValue());
77
80
  drawingManager.addDrawer(this.backgroundDrawer, 'MAIN_BACKGROUND');
78
81
  cursorHandler.setCursorForCanvasEl(CanvasElement.PANE_UUID(CHART_UUID), config.components.chart.cursor);
79
82
  this.dataSeriesDrawer = new DataSeriesDrawer(paneManager, this.dataSeriesDrawers);
@@ -104,6 +107,13 @@ export class ChartComponent extends ChartBaseElement {
104
107
  this.addRxSubscription(this.paneManager.dataSeriesRemovedSubject.subscribe(series => {
105
108
  this.dynamicObjects.model.removeObject(series.id);
106
109
  }));
110
+ // redraw background only when chart is resized
111
+ this.addRxSubscription(this.canvasBoundsContainer.observeAnyBoundsChanged().subscribe(() => {
112
+ this.backgroundDrawPredicateSubj.next(false);
113
+ }));
114
+ this.addRxSubscription(this.chartResizeHandler.canvasResized.subscribe(() => {
115
+ this.backgroundDrawPredicateSubj.next(true);
116
+ }));
107
117
  }
108
118
  /**
109
119
  * Registers default candle transformers.
@@ -162,7 +172,8 @@ export class ChartComponent extends ChartBaseElement {
162
172
  this.registerDataSeriesTypeDrawer('area', new AreaDrawer(this.config.components.chart));
163
173
  this.registerDataSeriesTypeDrawer('baseline', new BaselineDrawer(this.baselineModel, this.canvasBoundsContainer));
164
174
  this.registerDataSeriesTypeDrawer('histogram', new MainChartHistogramDrawer(this.config.components.chart.histogram));
165
- const mainChartBoundsProvider = () => this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(CHART_UUID));
175
+ const chartPaneId = CanvasElement.PANE_UUID(CHART_UUID);
176
+ const mainChartBoundsProvider = () => this.canvasBoundsContainer.getBounds(chartPaneId);
166
177
  this.registerDataSeriesTypeDrawer('LINEAR', new LinearDrawer());
167
178
  this.registerDataSeriesTypeDrawer('HISTOGRAM', new HistogramDrawer());
168
179
  this.registerDataSeriesTypeDrawer('TREND_HISTOGRAM', new TrendHistogramDrawer());
@@ -196,16 +207,16 @@ export class ChartComponent extends ChartBaseElement {
196
207
  * @param {Timestamp} end - The end timestamp of the range.
197
208
  * @returns {void}
198
209
  */
199
- setTimestampRange(start, end) {
200
- return this.chartModel.setTimestampRange(start, end);
210
+ setTimestampRange(start, end, forceNoAnimation = true) {
211
+ return this.chartModel.setTimestampRange(start, end, forceNoAnimation);
201
212
  }
202
213
  /**
203
214
  * Moves the viewport to exactly xStart..xEnd place.
204
215
  * @param xStart - viewport start in units
205
216
  * @param xEnd - viewport end in units
206
217
  */
207
- setXScale(xStart, xEnd) {
208
- return this.scale.setXScale(xStart, xEnd);
218
+ setXScale(xStart, xEnd, forceNoAnimation = true) {
219
+ return this.scale.setXScale(xStart, xEnd, forceNoAnimation);
209
220
  }
210
221
  /**
211
222
  * Sets the visibility of the wicks in the chart.
@@ -49,7 +49,6 @@ export declare class ChartModel extends ChartBaseElement {
49
49
  readonly nextCandleTimeStampSubject: Subject<void>;
50
50
  readonly chartTypeChanged: Subject<BarType>;
51
51
  readonly mainInstrumentChangedSubject: Subject<ChartInstrument>;
52
- readonly scaleInversedSubject: Subject<void>;
53
52
  readonly offsetsChanged: Subject<void>;
54
53
  private candlesTransformersByChartType;
55
54
  lastCandleLabelsByChartType: Partial<Record<BarType, LastCandleLabelHandler>>;
@@ -319,7 +318,7 @@ export declare class ChartModel extends ChartBaseElement {
319
318
  * @param {Timestamp} end - The end timestamp of the range.
320
319
  * @returns {void}
321
320
  */
322
- setTimestampRange(start: Timestamp, end: Timestamp): void;
321
+ setTimestampRange(start: Timestamp, end: Timestamp, forceNoAnimation?: boolean): void;
323
322
  /**
324
323
  * Returns the last candle of the main candle series.
325
324
  * @returns {Candle | undefined} The last candle of the main candle series or undefined if the series is empty.
@@ -50,7 +50,6 @@ export class ChartModel extends ChartBaseElement {
50
50
  this.nextCandleTimeStampSubject = new Subject();
51
51
  this.chartTypeChanged = new Subject();
52
52
  this.mainInstrumentChangedSubject = new Subject();
53
- this.scaleInversedSubject = new Subject();
54
53
  this.offsetsChanged = new Subject();
55
54
  this.candlesTransformersByChartType = {};
56
55
  this.lastCandleLabelsByChartType = {};
@@ -656,11 +655,11 @@ export class ChartModel extends ChartBaseElement {
656
655
  * @param {Timestamp} end - The end timestamp of the range.
657
656
  * @returns {void}
658
657
  */
659
- setTimestampRange(start, end) {
658
+ setTimestampRange(start, end, forceNoAnimation = true) {
660
659
  const startUnit = this.candleFromTimestamp(start).startUnit;
661
660
  const endCandle = this.candleFromTimestamp(end);
662
661
  const endUnit = endCandle.startUnit + endCandle.width;
663
- return this.scale.setXScale(startUnit, endUnit);
662
+ return this.scale.setXScale(startUnit, endUnit, forceNoAnimation);
664
663
  }
665
664
  /**
666
665
  * Returns the last candle of the main candle series.
@@ -107,7 +107,7 @@ export class CrossToolModel extends ChartBaseElement {
107
107
  else {
108
108
  this.currentHover.y = hover.y;
109
109
  }
110
- this.currentHover.paneId = CHART_UUID;
110
+ this.currentHover.paneId = hover.paneId;
111
111
  this.currentHoverSubject.next(this.currentHover);
112
112
  }
113
113
  }
@@ -122,6 +122,7 @@ export class CrossAndLabelsDrawerType {
122
122
  if (this.config.components.yAxis.visible) {
123
123
  const pane = this.paneManager.panes[point.paneId];
124
124
  const y = point.y;
125
+ const type = this.config.components.crossTool.yLabel.type;
125
126
  if (!pane) {
126
127
  return;
127
128
  }
@@ -129,9 +130,10 @@ export class CrossAndLabelsDrawerType {
129
130
  const price = extent.regularValueFromY(y);
130
131
  const label = extent.valueFormatter(price);
131
132
  const bounds = this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID_Y_AXIS(pane.uuid, extent.idx));
132
- const drawYLabel = priceLabelDrawersMap[this.config.components.crossTool.yLabel.type];
133
+ const drawYLabel = priceLabelDrawersMap[type];
134
+ const textColor = type === 'plain' ? crossToolColors.lineColor : crossToolColors.labelTextColor;
133
135
  drawYLabel(ctx, bounds, label, y, {
134
- textColor: crossToolColors.labelTextColor,
136
+ textColor,
135
137
  bgColor: crossToolColors.labelBoxColor,
136
138
  paddingBottom: yLabelPadding === null || yLabelPadding === void 0 ? void 0 : yLabelPadding.bottom,
137
139
  paddingEnd: yLabelPadding === null || yLabelPadding === void 0 ? void 0 : yLabelPadding.end,
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import { CanvasElement } from '../../canvas/canvas-bounds-container';
7
7
  import { getTextLineHeight } from '../../utils/canvas/canvas-text-functions.utils';
8
+ import { clipToBounds } from '../../utils/canvas/canvas-drawing-functions.utils';
8
9
  export class HighLowDrawer {
9
10
  constructor(canvasModel, chartModel, config, canvasBoundsContainer) {
10
11
  this.canvasModel = canvasModel;
@@ -34,7 +35,10 @@ export class HighLowDrawer {
34
35
  ctx.font = this.config.components.highLow.font;
35
36
  this.drawMarkerLabel(ctx, finalHighIdx, high, 'high');
36
37
  this.drawMarkerLabel(ctx, finalLowIdx, low, 'low');
38
+ const chartBounds = this.canvasBoundsContainer.getBounds('PANE_CHART');
37
39
  ctx.restore();
40
+ // We need clip here so lowLabel won't overlap other panes
41
+ clipToBounds(ctx, chartBounds);
38
42
  }
39
43
  }
40
44
  /**
@@ -47,7 +51,10 @@ export class HighLowDrawer {
47
51
  */
48
52
  drawMarkerLabel(ctx, candleIdx, yValue, type) {
49
53
  const y = this.getMarkerY(ctx, yValue, type === 'low');
50
- if (!this.checkMarkerInBounds(y)) {
54
+ const fontSize = getTextLineHeight(ctx, false);
55
+ // we need to measure fit into the bounds for low label by its top point
56
+ const yForBoundsTrack = type === 'low' ? y - fontSize : y;
57
+ if (!this.checkMarkerInBounds(yForBoundsTrack)) {
51
58
  return;
52
59
  }
53
60
  const text = this.getMarkerText(yValue, type);
@@ -79,7 +86,7 @@ export class HighLowDrawer {
79
86
  getMarkerY(ctx, yValue, offset = false) {
80
87
  const y = this.chartModel.toY(yValue);
81
88
  if (offset) {
82
- const fontSize = getTextLineHeight(ctx);
89
+ const fontSize = getTextLineHeight(ctx, false);
83
90
  return y + fontSize;
84
91
  }
85
92
  return y;
@@ -7,7 +7,7 @@ import { calculateTextWidth } from '../../utils/canvas/canvas-font-measure-tool.
7
7
  import { HIGHLIGHTS_TYPES } from './highlights.model';
8
8
  import { CanvasElement } from '../../canvas/canvas-bounds-container';
9
9
  import { unitToPixels } from '../../model/scaling/viewport.model';
10
- import { clipToBounds } from '../../drawers/data-series.drawer';
10
+ import { clipToBounds } from '../../utils/canvas/canvas-drawing-functions.utils';
11
11
  const LABEL_PADDINGS = [20, 10];
12
12
  export class HighlightsDrawer {
13
13
  constructor(highlightsModel, chartModel, canvasModel, canvasBoundsContainer, config) {
@@ -85,7 +85,8 @@ export class PaneComponent extends ChartBaseElement {
85
85
  * @returns {GridComponent} - The newly created GridComponent instance.
86
86
  */
87
87
  createGridComponent(uuid, scale, yAxisLabelsGenerator, yAxisState) {
88
- const gridComponent = new GridComponent(this.mainCanvasModel, scale, this.config, yAxisState, `PANE_${uuid}_grid_drawer`, this.drawingManager, () => this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(uuid)), () => this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(uuid)), () => [], () => yAxisLabelsGenerator.generateNumericLabels());
88
+ const chartPaneId = CanvasElement.PANE_UUID(uuid);
89
+ const gridComponent = new GridComponent(this.mainCanvasModel, scale, this.config, yAxisState, `PANE_${uuid}_grid_drawer`, this.drawingManager, () => this.canvasBoundsContainer.getBounds(chartPaneId), () => this.canvasBoundsContainer.getBounds(chartPaneId), () => [], () => yAxisLabelsGenerator.generateNumericLabels());
89
90
  return gridComponent;
90
91
  }
91
92
  /**
@@ -96,7 +97,8 @@ export class PaneComponent extends ChartBaseElement {
96
97
  * @returns {Unsubscriber}
97
98
  */
98
99
  createYPanHandler(uuid, scale) {
99
- const dragNDropComponent = this.chartPanComponent.chartAreaPanHandler.registerChartYPanHandler(scale, this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.PANE_UUID(uuid)));
100
+ const chartPaneId = CanvasElement.PANE_UUID(uuid);
101
+ const dragNDropComponent = this.chartPanComponent.chartAreaPanHandler.registerChartYPanHandler(scale, this.canvasBoundsContainer.getBoundsHitTest(chartPaneId));
100
102
  return [
101
103
  () => {
102
104
  this.chartPanComponent.chartAreaPanHandler.removeChildEntity(dragNDropComponent);
@@ -113,7 +115,8 @@ export class PaneComponent extends ChartBaseElement {
113
115
  createExtentComponent(options) {
114
116
  var _a, _b;
115
117
  const extentIdx = this.yExtentComponents.length;
116
- const getBounds = () => this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(this.uuid));
118
+ const chartPaneId = CanvasElement.PANE_UUID(this.uuid);
119
+ const getBounds = () => this.canvasBoundsContainer.getBounds(chartPaneId);
117
120
  const scaleModel = (_a = options === null || options === void 0 ? void 0 : options.scale) !== null && _a !== void 0 ? _a : new SyncedByXScaleModel(this.mainScale, this.config, getBounds, this.canvasAnimation);
118
121
  const [unsub, dragNDrop] = this.createYPanHandler(this.uuid, scaleModel);
119
122
  // creating partially resolved constructor except formatter & dataSeriesProvider - bcs it's not possible to provide formatter
@@ -40,6 +40,7 @@ export class SnapshotComponent extends ChartBaseElement {
40
40
  ctx.drawImage(this.elements.mainCanvas, 0, 0, width, height);
41
41
  ctx.drawImage(this.elements.dynamicObjectsCanvas, 0, 0, width, height);
42
42
  ctx.drawImage(this.elements.crossToolCanvas, 0, 0, width, height);
43
+ ctx.drawImage(this.elements.yAxisLabelsCanvas, 0, 0, width, height);
43
44
  userDrawCallback && userDrawCallback(ctx);
44
45
  return new Promise((resolve, fail) => this.elements.snapshotCanvas.toBlob(blob => {
45
46
  return blob ? resolve(blob) : fail('Blob is null');
@@ -31,9 +31,10 @@ class SeparateVolumesComponent extends ChartBaseElement {
31
31
  */
32
32
  activateSeparateVolumes() {
33
33
  if (this.paneManager.panes[SeparateVolumesComponent.UUID] === undefined) {
34
+ const precision = 1;
34
35
  const volumePane = this.paneManager.createPane(SeparateVolumesComponent.UUID, {
35
36
  paneFormatters: {
36
- regular: volumeFormatter,
37
+ regular: (value) => volumeFormatter(value, precision),
37
38
  },
38
39
  useDefaultHighLow: false,
39
40
  increment: 1,
@@ -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 { clipToBounds } from '../../drawers/data-series.drawer';
6
+ import { clipToBounds } from '../../utils/canvas/canvas-drawing-functions.utils';
7
7
  import { unitToPixels } from '../../model/scaling/viewport.model';
8
8
  import { flat } from '../../utils/array.utils';
9
9
  import { ceilToDPR, floorToDPR } from '../../utils/device/device-pixel-ratio.utils';
@@ -3,4 +3,4 @@
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
- export declare const volumeFormatter: (value: number) => string;
6
+ export declare const volumeFormatter: (value: number, precision?: number) => string;
@@ -3,34 +3,37 @@
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
- const DEFAULT_PRECISION = 5;
7
- const MIN_VALUE = 0.0000000001;
8
- const TRAILLING_ZEROES_REGEXP = /\.?0+$/;
9
- const TRAILLING_FRACTION_WITH_ZEROES_REGEXP = /(\.[1-9]*)0+$/;
10
- export const volumeFormatter = (value) => {
11
- const formatValue = (value, amountToCut) => {
12
- const rounder = Math.pow(10, DEFAULT_PRECISION);
13
- const roundedValue = Math.round(value * rounder) / rounder;
14
- if (roundedValue < 1 && roundedValue >= MIN_VALUE) {
15
- return roundedValue
16
- .toFixed(DEFAULT_PRECISION)
17
- .replace(TRAILLING_ZEROES_REGEXP, '')
18
- .replace(TRAILLING_FRACTION_WITH_ZEROES_REGEXP, '');
6
+ export const volumeFormatter = (value, precision = 1) => {
7
+ function formatNumber(value) {
8
+ let formattedResult;
9
+ const priceScale = Math.pow(10, precision);
10
+ value = Math.round(value * priceScale) / priceScale;
11
+ if (value >= 1e-15 && value < 1) {
12
+ formattedResult = value.toFixed(precision).replace(/\.?0+$/, ''); // regex removes trailing zeroes
19
13
  }
20
14
  else {
21
- return (roundedValue + '').replace(TRAILLING_FRACTION_WITH_ZEROES_REGEXP, '') + (amountToCut || '');
15
+ formattedResult = String(value);
22
16
  }
23
- };
24
- if (Math.abs(value) > 999999999) {
25
- value = Math.round(value / 1000000) * 1000000;
26
- return formatValue(value / 1000000000, 'B');
17
+ return formattedResult.replace(/(\.[1-9]*)0+$/, (e, p1) => p1);
27
18
  }
28
- if (Math.abs(value) > 999999) {
29
- value = 1000 * Math.round(value / 1000);
30
- return formatValue(value / 1000000, 'M');
31
- }
32
- if (Math.abs(value) > 9999) {
33
- return formatValue(value / 1000, 'K');
19
+ function format(value) {
20
+ let sign = '';
21
+ if (value < 0) {
22
+ sign = '-';
23
+ value = -value;
24
+ }
25
+ if (value < 995) {
26
+ return sign + formatNumber(value);
27
+ }
28
+ if (value < 999995) {
29
+ return sign + formatNumber(value / 1000) + 'K';
30
+ }
31
+ if (value < 999999995) {
32
+ value = 1000 * Math.round(value / 1000);
33
+ return sign + formatNumber(value / 1000000) + 'M';
34
+ }
35
+ value = 1000000 * Math.round(value / 1000000);
36
+ return sign + formatNumber(value / 1000000000) + 'B';
34
37
  }
35
- return formatValue(value);
38
+ return format(value);
36
39
  };
@@ -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 { eachDayOfInterval, isSameDay, isMonday, isTuesday, isWednesday, isThursday, isFriday, isSaturday, isSunday, startOfMonth, endOfMonth, } from 'date-fns/esm';
6
+ import { eachDayOfInterval, isSameDay, isMonday, isTuesday, isWednesday, isThursday, isFriday, isSaturday, isSunday, startOfMonth, endOfMonth, } from 'date-fns';
7
7
  /**
8
8
  * Factory that return a {@link TimeFormatMatcher} function for a given {@link ParsedTimeFormats}
9
9
  * @see
@@ -27,7 +27,7 @@ export interface ParsedNCTimeFormat {
27
27
  }
28
28
  export type ParsedTimeFormat = ParsedCTimeFormat | ParsedWeekFormat | ParsedNCTimeFormat;
29
29
  export type SpecialSymbol = '!' | '$';
30
- export declare const timeFormatConfirugableGuard: (key: string) => key is "second" | "minute" | "hour" | "day" | "month" | "year";
30
+ export declare const timeFormatConfirugableGuard: (key: string) => key is "year" | "month" | "day" | "hour" | "minute" | "second";
31
31
  export declare const weekWeekdayGuard: (key: string) => key is "week-weekday";
32
32
  export declare const timeFormatNoNConfirugableGuard: (key: string) => key is "lessThanSecond";
33
33
  export {};
@@ -51,7 +51,7 @@ export const getWeightFromTimeFormat = (format) => {
51
51
  */
52
52
  export const groupLabelsByWeight = (weightedLabels) => {
53
53
  const labelsGroupedByWeight = {};
54
- weightedLabels.forEach(weightedLabel => {
54
+ for (const weightedLabel of weightedLabels) {
55
55
  const labelsByWeight = labelsGroupedByWeight[weightedLabel.weight];
56
56
  if (labelsByWeight === undefined) {
57
57
  labelsGroupedByWeight[weightedLabel.weight] = [weightedLabel];
@@ -59,7 +59,7 @@ export const groupLabelsByWeight = (weightedLabels) => {
59
59
  else {
60
60
  labelsByWeight.push(weightedLabel);
61
61
  }
62
- });
62
+ }
63
63
  return labelsGroupedByWeight;
64
64
  };
65
65
  /**