@devexperts/dxcharts-lite 2.5.5 → 2.5.7

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 (34) hide show
  1. package/dist/chart/bootstrap.js +1 -1
  2. package/dist/chart/canvas/canvas-bounds-container.d.ts +21 -0
  3. package/dist/chart/canvas/canvas-bounds-container.js +31 -1
  4. package/dist/chart/chart.js +2 -1
  5. package/dist/chart/components/chart/basic-scale.js +0 -1
  6. package/dist/chart/components/chart/chart.model.d.ts +0 -21
  7. package/dist/chart/components/chart/chart.model.js +3 -33
  8. package/dist/chart/components/pan/chart-pan.component.js +2 -1
  9. package/dist/chart/components/pane/pane-manager.component.d.ts +3 -1
  10. package/dist/chart/components/pane/pane-manager.component.js +3 -2
  11. package/dist/chart/components/pane/pane.component.d.ts +3 -1
  12. package/dist/chart/components/pane/pane.component.js +3 -2
  13. package/dist/chart/components/x_axis/x-axis-scale.handler.d.ts +4 -2
  14. package/dist/chart/components/x_axis/x-axis-scale.handler.js +16 -8
  15. package/dist/chart/components/x_axis/x-axis.component.js +1 -1
  16. package/dist/chart/components/y_axis/price_labels/y-axis-labels.model.d.ts +3 -1
  17. package/dist/chart/components/y_axis/price_labels/y-axis-labels.model.js +5 -3
  18. package/dist/chart/components/y_axis/y-axis-scale.handler.d.ts +1 -0
  19. package/dist/chart/components/y_axis/y-axis-scale.handler.js +18 -1
  20. package/dist/chart/components/y_axis/y-axis.component.d.ts +3 -1
  21. package/dist/chart/components/y_axis/y-axis.component.js +3 -2
  22. package/dist/chart/components/y_axis/y-axis.model.d.ts +2 -1
  23. package/dist/chart/components/y_axis/y-axis.model.js +2 -2
  24. package/dist/chart/inputhandlers/main-canvas-touch.handler.d.ts +3 -1
  25. package/dist/chart/inputhandlers/main-canvas-touch.handler.js +4 -3
  26. package/dist/chart/model/scale.model.d.ts +5 -10
  27. package/dist/chart/model/scale.model.js +35 -34
  28. package/dist/chart/model/scaling/lock-ratio.model.d.ts +6 -6
  29. package/dist/chart/model/scaling/lock-ratio.model.js +27 -21
  30. package/dist/chart/model/scaling/viewport.model.js +6 -1
  31. package/dist/chart/utils/color.utils.d.ts +3 -0
  32. package/dist/chart/utils/color.utils.js +5 -1
  33. package/dist/dxchart.min.js +4 -4
  34. package/package.json +1 -1
@@ -8,12 +8,13 @@ import { ChartBaseElement } from '../model/chart-base-element';
8
8
  * Handles chart touch events.
9
9
  */
10
10
  export class MainCanvasTouchHandler extends ChartBaseElement {
11
- constructor(chartAreaPanHandler, scale, canvasInputListeners, mainCanvasParent) {
11
+ constructor(chartAreaPanHandler, scale, canvasInputListeners, mainCanvasParent, hitTest) {
12
12
  super();
13
13
  this.chartAreaPanHandler = chartAreaPanHandler;
14
14
  this.scale = scale;
15
15
  this.canvasInputListeners = canvasInputListeners;
16
16
  this.mainCanvasParent = mainCanvasParent;
17
+ this.hitTest = hitTest;
17
18
  // 2 candles indexes touched by 2 fingers when pinching
18
19
  this.touchedCandleIndexes = [0, 0];
19
20
  }
@@ -23,8 +24,8 @@ export class MainCanvasTouchHandler extends ChartBaseElement {
23
24
  * @returns {void}
24
25
  */
25
26
  doActivate() {
26
- this.addRxSubscription(this.canvasInputListeners.observeTouchStart().subscribe(e => this.handleTouchStartEvent(e)));
27
- this.addRxSubscription(this.canvasInputListeners.observeTouchMove().subscribe(e => this.handleTouchMoveEvent(e)));
27
+ this.addRxSubscription(this.canvasInputListeners.observeTouchStart(this.hitTest).subscribe(e => this.handleTouchStartEvent(e)));
28
+ this.addRxSubscription(this.canvasInputListeners.observeTouchMove(this.hitTest).subscribe(e => this.handleTouchMoveEvent(e)));
28
29
  this.addRxSubscription(this.canvasInputListeners.observeTouchEndDocument().subscribe(e => this.handleTouchEndEvent(e)));
29
30
  }
30
31
  /**
@@ -7,7 +7,6 @@ import { Subject } from 'rxjs';
7
7
  import { ChartConfigComponentsOffsets, ChartScale, FullChartConfig } from '../chart.config';
8
8
  import { CanvasAnimation } from '../animation/canvas-animation';
9
9
  import { AutoScaleViewportSubModel } from './scaling/auto-scale.model';
10
- import { ZoomXToZoomYRatio } from './scaling/lock-ratio.model';
11
10
  import { Price, Unit, ViewportModel, ViewportModelState, Zoom } from './scaling/viewport.model';
12
11
  import { BoundsProvider } from './bounds.model';
13
12
  export interface HighLowWithIndex {
@@ -26,8 +25,8 @@ export declare const getDefaultHighLowWithIndex: () => HighLowWithIndex;
26
25
  export type ViewportPercent = number;
27
26
  type Constraints = (initialState: ViewportModelState, state: ViewportModelState) => ViewportModelState;
28
27
  export interface ZoomReached {
29
- max: boolean;
30
- min: boolean;
28
+ zoomIn: boolean;
29
+ zoomOut: boolean;
31
30
  }
32
31
  /**
33
32
  * The ScaleModel class represents the state of a chart's scale, including the current viewport, zoom level, and auto-scaling settings.
@@ -46,7 +45,6 @@ export declare class ScaleModel extends ViewportModel {
46
45
  scaleInversedSubject: Subject<boolean>;
47
46
  beforeStartAnimationSubject: Subject<void>;
48
47
  autoScaleModel: AutoScaleViewportSubModel;
49
- zoomXYRatio: ZoomXToZoomYRatio;
50
48
  zoomReached: ZoomReached;
51
49
  readonly state: ChartScale;
52
50
  history: ScaleHistoryItem[];
@@ -88,8 +86,8 @@ export declare class ScaleModel extends ViewportModel {
88
86
  haltAnimation(): void;
89
87
  private zoomXTo;
90
88
  calculateZoomReached(zoomX: Unit, zoomIn?: boolean): {
91
- max: boolean;
92
- min: boolean;
89
+ zoomIn: boolean;
90
+ zoomOut: boolean;
93
91
  };
94
92
  /**
95
93
  * Moves the viewport to exactly xStart..xEnd place.
@@ -101,6 +99,7 @@ export declare class ScaleModel extends ViewportModel {
101
99
  */
102
100
  setXScale(xStart: Unit, xEnd: Unit, forceNoAnimation?: boolean): void;
103
101
  setYScale(yStart: Unit, yEnd: Unit, fire?: boolean): void;
102
+ private setLockedYScale;
104
103
  /**
105
104
  * Moves both xStart and xEnd without changing the viewport width (zoom).
106
105
  * Works without animation.
@@ -165,10 +164,6 @@ export declare class ScaleModel extends ViewportModel {
165
164
  * @param value - If true, the price-to-bar ratio will be locked. If false, it will not be locked.
166
165
  */
167
166
  setLockPriceToBarRatio(value?: boolean): void;
168
- /**
169
- * Recalculates the zoom X/Y ratio based on the current zoom levels.
170
- */
171
- recalculateZoomXYRatio(): void;
172
167
  }
173
168
  /**
174
169
  * The SyncedByXScaleModel class extends the ScaleModel class and adds support for synchronization with other ScaleModel instance, so both instances maintain the same X-axis bounds.
@@ -7,7 +7,7 @@ import { Subject } from 'rxjs';
7
7
  import { startViewportModelAnimation } from '../animation/viewport-model-animation';
8
8
  import { cloneUnsafe } from '../utils/object.utils';
9
9
  import { AutoScaleViewportSubModel } from './scaling/auto-scale.model';
10
- import { changeXToKeepRatio, changeYToKeepRatio, ratioFromZoomXY } from './scaling/lock-ratio.model';
10
+ import { changeXToKeepRatio, changeYToKeepRatio } from './scaling/lock-ratio.model';
11
11
  import { moveXStart, moveYStart } from './scaling/move-chart.functions';
12
12
  import { ViewportModel, calculateZoom, compareStates, } from './scaling/viewport.model';
13
13
  import { zoomXToEndViewportCalculator, zoomXToPercentViewportCalculator } from './scaling/x-zooming.functions';
@@ -36,8 +36,7 @@ export class ScaleModel extends ViewportModel {
36
36
  this.scaleInversedSubject = new Subject();
37
37
  // y-axis component needs this subject in order to halt prev animation if axis type is percent
38
38
  this.beforeStartAnimationSubject = new Subject();
39
- this.zoomXYRatio = 0;
40
- this.zoomReached = { min: false, max: false };
39
+ this.zoomReached = { zoomIn: false, zoomOut: false };
41
40
  // TODO rework, make a new history based on units
42
41
  this.history = [];
43
42
  this.xConstraints = [];
@@ -129,11 +128,11 @@ export class ScaleModel extends ViewportModel {
129
128
  const initialStateCopy = Object.assign({}, state);
130
129
  const constrainedState = this.scalePostProcessor(initialStateCopy, state);
131
130
  this.zoomReached = this.calculateZoomReached(constrainedState.zoomX, zoomIn);
132
- if (this.zoomReached.max || this.zoomReached.min) {
131
+ if (this.zoomReached.zoomIn || this.zoomReached.zoomOut) {
133
132
  return;
134
133
  }
135
134
  if (this.state.lockPriceToBarRatio) {
136
- changeYToKeepRatio(constrainedState, this.zoomXYRatio);
135
+ changeYToKeepRatio(initialStateCopy, constrainedState);
137
136
  }
138
137
  if (this.state.auto) {
139
138
  this.autoScaleModel.doAutoYScale(constrainedState);
@@ -149,15 +148,17 @@ export class ScaleModel extends ViewportModel {
149
148
  const chartWidth = this.getBounds().width;
150
149
  const delta = 0.001; // zoom values are very precise and should be compared with some precision delta
151
150
  if (chartWidth > 0) {
152
- const maxZoomReached = zoomX - calculateZoom(this.config.components.chart.minCandles, chartWidth) <= delta;
153
- // max zoom reached and trying to zoom in further
154
- const maxZoomDisabled = maxZoomReached && zoomIn;
155
- const minZoomReached = zoomX - calculateZoom(chartWidth / this.config.components.chart.minWidth, chartWidth) >= delta;
156
- // min zoom reached and trying to zoom out further
157
- const minZoomDisabled = minZoomReached && !zoomIn;
158
- return { max: maxZoomDisabled, min: minZoomDisabled };
151
+ const maxZoomIn = calculateZoom(this.config.components.chart.minCandles, chartWidth);
152
+ const maxZoomInReached = zoomX !== maxZoomIn && zoomX - maxZoomIn <= delta;
153
+ // max zoom in reached and trying to zoom in further
154
+ const maxZoomInDisabled = maxZoomInReached && zoomIn;
155
+ const maxZoomOut = calculateZoom(chartWidth / this.config.components.chart.minWidth, chartWidth);
156
+ const maxZoomOutReached = zoomX - maxZoomOut >= delta;
157
+ // max zoom out reached and trying to zoom out further
158
+ const maxZoomOutDisabled = maxZoomOutReached && !zoomIn;
159
+ return { zoomIn: maxZoomInDisabled, zoomOut: maxZoomOutDisabled };
159
160
  }
160
- return { max: false, min: false };
161
+ return { zoomIn: false, zoomOut: false };
161
162
  }
162
163
  /**
163
164
  * Moves the viewport to exactly xStart..xEnd place.
@@ -177,11 +178,11 @@ export class ScaleModel extends ViewportModel {
177
178
  const constrainedState = this.scalePostProcessor(initialState, state);
178
179
  const zoomIn = constrainedState.xEnd - constrainedState.xStart < initialState.xEnd - initialState.xStart;
179
180
  this.zoomReached = this.calculateZoomReached(zoomX, zoomIn);
180
- if (this.zoomReached.max || this.zoomReached.min) {
181
+ if (this.zoomReached.zoomIn || this.zoomReached.zoomOut) {
181
182
  return;
182
183
  }
183
184
  if (this.state.lockPriceToBarRatio) {
184
- changeYToKeepRatio(constrainedState, this.zoomXYRatio);
185
+ changeYToKeepRatio(initialState, constrainedState);
185
186
  }
186
187
  if (this.state.auto) {
187
188
  this.autoScaleModel.doAutoYScale(constrainedState);
@@ -199,21 +200,30 @@ export class ScaleModel extends ViewportModel {
199
200
  if (initialState.yStart === yStart && initialState.yEnd === yEnd && initialState.zoomY > 0) {
200
201
  return;
201
202
  }
203
+ if (this.state.lockPriceToBarRatio) {
204
+ this.setLockedYScale(yStart, yEnd, fire, initialState);
205
+ return;
206
+ }
202
207
  super.setYScale(yStart, yEnd, fire);
203
208
  const state = this.export();
204
209
  const constrainedState = this.scalePostProcessor(initialState, state);
205
- if (this.state.lockPriceToBarRatio) {
206
- changeXToKeepRatio(constrainedState, this.zoomXYRatio);
207
- this.setXScale(constrainedState.xStart, constrainedState.xEnd);
208
- // TODO: rewrite logic for applying constraints to consider both axes, now constraints on Y may not work correctly
209
- return;
210
+ if (this.state.auto) {
211
+ this.autoScaleModel.doAutoYScale(constrainedState);
210
212
  }
211
- else {
212
- if (this.state.auto) {
213
- this.autoScaleModel.doAutoYScale(constrainedState);
214
- }
215
- this.apply(constrainedState);
213
+ this.apply(constrainedState);
214
+ }
215
+ setLockedYScale(yStart, yEnd, fire = false, initialState) {
216
+ const zoomIn = yEnd < initialState.yEnd;
217
+ if ((this.zoomReached.zoomOut && zoomIn === false) || (this.zoomReached.zoomIn && zoomIn === true)) {
218
+ return;
216
219
  }
220
+ super.setYScale(yStart, yEnd, fire);
221
+ const state = this.export();
222
+ const constrainedState = this.scalePostProcessor(initialState, state);
223
+ changeXToKeepRatio(initialState, constrainedState);
224
+ this.zoomReached = this.calculateZoomReached(constrainedState.zoomX, zoomIn);
225
+ this.apply(constrainedState);
226
+ this.fireChanged();
217
227
  }
218
228
  /**
219
229
  * Moves both xStart and xEnd without changing the viewport width (zoom).
@@ -342,17 +352,8 @@ export class ScaleModel extends ViewportModel {
342
352
  this.state.lockPriceToBarRatio = false;
343
353
  return;
344
354
  }
345
- if (value) {
346
- this.recalculateZoomXYRatio();
347
- }
348
355
  this.state.lockPriceToBarRatio = value;
349
356
  }
350
- /**
351
- * Recalculates the zoom X/Y ratio based on the current zoom levels.
352
- */
353
- recalculateZoomXYRatio() {
354
- this.zoomXYRatio = ratioFromZoomXY(this.zoomX, this.zoomY);
355
- }
356
357
  }
357
358
  /**
358
359
  * The SyncedByXScaleModel class extends the ScaleModel class and adds support for synchronization with other ScaleModel instance, so both instances maintain the same X-axis bounds.
@@ -10,13 +10,13 @@ export declare const zoomXToZoomY: (zoomX: Zoom, ratio: ZoomXToZoomYRatio) => Zo
10
10
  export declare const zoomYToZoomX: (zoomY: Zoom, ratio: ZoomXToZoomYRatio) => Zoom;
11
11
  /**
12
12
  * Locks the zoomY with zoomX and zooms y-scale depending on x-scale.
13
- * @param state
14
- * @param zoomXYRatio
13
+ * @param prevState
14
+ * @param newState
15
15
  */
16
- export declare const changeYToKeepRatio: (state: ViewportModelState, zoomXYRatio: ZoomXToZoomYRatio) => void;
16
+ export declare const changeYToKeepRatio: (prevState: ViewportModelState, newState: ViewportModelState) => void;
17
17
  /**
18
18
  * Locks the zoomY with zoomX and zooms x-scale depending on y-scale.
19
- * @param state
20
- * @param zoomXYRatio
19
+ * @param prevState
20
+ * @param newState
21
21
  */
22
- export declare const changeXToKeepRatio: (state: ViewportModelState, zoomXYRatio: ZoomXToZoomYRatio) => void;
22
+ export declare const changeXToKeepRatio: (prevState: ViewportModelState, newState: ViewportModelState) => void;
@@ -8,30 +8,36 @@ export const zoomXToZoomY = (zoomX, ratio) => zoomX / ratio;
8
8
  export const zoomYToZoomX = (zoomY, ratio) => zoomY * ratio;
9
9
  /**
10
10
  * Locks the zoomY with zoomX and zooms y-scale depending on x-scale.
11
- * @param state
12
- * @param zoomXYRatio
11
+ * @param prevState
12
+ * @param newState
13
13
  */
14
- export const changeYToKeepRatio = (state, zoomXYRatio) => {
15
- const prevZoomY = state.zoomY;
16
- state.zoomY = zoomXToZoomY(state.zoomX, zoomXYRatio);
17
- const zoomYMult = state.zoomY / prevZoomY;
18
- const lastYHeight = state.yEnd - state.yStart;
19
- const newYHeight = lastYHeight * zoomYMult;
20
- const delta = newYHeight - lastYHeight;
21
- state.yEnd = state.yEnd + delta / 2;
22
- state.yStart = state.yStart - delta / 2;
14
+ export const changeYToKeepRatio = (prevState, newState) => {
15
+ const prevZoomX = prevState.zoomX;
16
+ const prevZoomY = prevState.zoomY;
17
+ const prevZoomXY = ratioFromZoomXY(prevZoomX, prevZoomY);
18
+ const prevYHeight = prevState.yEnd - prevState.yStart;
19
+ // recalculate zoomY
20
+ newState.zoomY = zoomXToZoomY(newState.zoomX, prevZoomXY);
21
+ const zoomYMult = newState.zoomY / prevZoomY;
22
+ const newYHeight = prevYHeight * zoomYMult;
23
+ const delta = newYHeight - prevYHeight;
24
+ newState.yEnd = newState.yEnd + delta / 2;
25
+ newState.yStart = newState.yStart - delta / 2;
23
26
  };
24
27
  /**
25
28
  * Locks the zoomY with zoomX and zooms x-scale depending on y-scale.
26
- * @param state
27
- * @param zoomXYRatio
29
+ * @param prevState
30
+ * @param newState
28
31
  */
29
- export const changeXToKeepRatio = (state, zoomXYRatio) => {
30
- const prevZoomX = state.zoomX;
31
- state.zoomX = zoomYToZoomX(state.zoomY, zoomXYRatio);
32
- const zoomXMult = state.zoomX / prevZoomX;
33
- const lastXWidth = state.xEnd - state.xStart;
34
- const newXWidth = lastXWidth * zoomXMult;
35
- const delta = newXWidth - lastXWidth;
36
- state.xStart = state.xStart - delta;
32
+ export const changeXToKeepRatio = (prevState, newState) => {
33
+ const prevZoomX = prevState.zoomX;
34
+ const prevZoomY = prevState.zoomY;
35
+ const prevZoomXY = ratioFromZoomXY(prevZoomX, prevZoomY);
36
+ const prevXWidth = prevState.xEnd - prevState.xStart;
37
+ // recalculate zoomX
38
+ newState.zoomX = zoomYToZoomX(newState.zoomY, prevZoomXY);
39
+ const zoomXMult = newState.zoomX / prevZoomX;
40
+ const newXWidth = prevXWidth * zoomXMult;
41
+ const delta = newXWidth - prevXWidth;
42
+ newState.xStart = newState.xStart - delta;
37
43
  };
@@ -287,7 +287,12 @@ export class ViewportModel extends ChartBaseElement {
287
287
  * @returns {boolean} - Returns true if the viewport is valid, false otherwise.
288
288
  */
289
289
  isViewportValid() {
290
- return this.xStart !== this.xEnd && this.yStart !== this.yEnd && isFinite(this.yStart) && isFinite(this.yEnd) && this.zoomX > 0 && this.zoomY > 0;
290
+ return (this.xStart !== this.xEnd &&
291
+ this.yStart !== this.yEnd &&
292
+ isFinite(this.yStart) &&
293
+ isFinite(this.yEnd) &&
294
+ this.zoomX > 0 &&
295
+ this.zoomY > 0);
291
296
  }
292
297
  }
293
298
  export const compareStates = (a, b) => !keys(a).some(k => a[k] !== b[k]);
@@ -3,4 +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
+ export declare const isHex: (color: string) => RegExpExecArray | null;
7
+ export declare const isRgb: (color: string) => RegExpExecArray | null;
8
+ export declare const isRgba: (color: string) => RegExpExecArray | null;
6
9
  export declare function toRGBA(color: string, alpha: number): string;
@@ -5,8 +5,12 @@
5
5
  */
6
6
  const HEX_COLOR_REGEXP = /^(#)([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i;
7
7
  const RGB_COLOR_REGEXP = /^\s*(rgba?)\s*[(]\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*[\d.]+\s*)?[)]\s*$/i;
8
+ const RGBA_COLOR_REGEXP = /^rgba[(](?:\s*0*(?:\d\d?(?:\.\d+)?(?:\s*%)?|\.\d+\s*%|100(?:\.0*)?\s*%|(?:1\d\d|2[0-4]\d|25[0-5])(?:\.\d+)?)\s*,){3}\s*0*(?:\.\d+|1(?:\.0*)?)\s*[)]$/;
9
+ export const isHex = (color) => HEX_COLOR_REGEXP.exec(color);
10
+ export const isRgb = (color) => RGB_COLOR_REGEXP.exec(color);
11
+ export const isRgba = (color) => RGBA_COLOR_REGEXP.exec(color);
8
12
  function parseColor(color) {
9
- const match = HEX_COLOR_REGEXP.exec(color) || RGB_COLOR_REGEXP.exec(color);
13
+ const match = isHex(color) || isRgb(color);
10
14
  let colors = [];
11
15
  if (match) {
12
16
  colors = match.slice(2, 5);