@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.
- package/dist/chart/bootstrap.js +4 -3
- package/dist/chart/canvas/canvas-bounds-container.d.ts +2 -2
- package/dist/chart/canvas/canvas-bounds-container.js +7 -5
- package/dist/chart/canvas/cursor.handler.js +2 -2
- package/dist/chart/chart.config.d.ts +17 -4
- package/dist/chart/chart.config.js +6 -2
- package/dist/chart/components/chart/chart-area-pan.handler.js +13 -8
- package/dist/chart/components/chart/chart.component.d.ts +6 -3
- package/dist/chart/components/chart/chart.component.js +18 -7
- package/dist/chart/components/chart/chart.model.d.ts +1 -2
- package/dist/chart/components/chart/chart.model.js +2 -3
- package/dist/chart/components/cross_tool/cross-tool.model.js +1 -1
- package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.js +4 -2
- package/dist/chart/components/high_low/high-low.drawer.js +9 -2
- package/dist/chart/components/highlights/highlights.drawer.js +1 -1
- package/dist/chart/components/pane/pane.component.js +6 -3
- package/dist/chart/components/snapshot/snapshot.component.js +1 -0
- package/dist/chart/components/volumes/separate-volumes.component.js +2 -1
- package/dist/chart/components/volumes/volumes.drawer.js +1 -1
- package/dist/chart/components/volumes/volumes.formatter.d.ts +1 -1
- package/dist/chart/components/volumes/volumes.formatter.js +28 -25
- package/dist/chart/components/x_axis/time/parser/time-formats-matchers.functions.js +1 -1
- package/dist/chart/components/x_axis/time/parser/time-formats.model.d.ts +1 -1
- package/dist/chart/components/x_axis/time/x-axis-weights.functions.js +2 -2
- package/dist/chart/components/x_axis/time/x-axis-weights.generator.js +6 -7
- package/dist/chart/components/x_axis/x-axis-labels.generator.d.ts +11 -3
- package/dist/chart/components/x_axis/x-axis-labels.generator.js +47 -19
- package/dist/chart/components/x_axis/x-axis-time-labels.drawer.js +0 -4
- package/dist/chart/components/x_axis/x-axis.component.js +7 -11
- package/dist/chart/components/y_axis/price_labels/last-candle-labels.provider.js +5 -5
- package/dist/chart/components/y_axis/price_labels/price-label.drawer.js +21 -22
- package/dist/chart/components/y_axis/y-axis-labels.drawer.d.ts +18 -6
- package/dist/chart/components/y_axis/y-axis-labels.drawer.js +23 -12
- package/dist/chart/components/y_axis/y-axis-scale.handler.d.ts +9 -4
- package/dist/chart/components/y_axis/y-axis-scale.handler.js +22 -15
- package/dist/chart/components/y_axis/y-axis.component.js +1 -0
- package/dist/chart/components/y_axis/y-axis.drawer.js +1 -1
- package/dist/chart/drawers/chart-background.drawer.d.ts +2 -3
- package/dist/chart/drawers/chart-background.drawer.js +16 -22
- package/dist/chart/drawers/data-series-drawers/candle-series-wrapper.js +1 -1
- package/dist/chart/drawers/data-series.drawer.d.ts +0 -2
- package/dist/chart/drawers/data-series.drawer.js +2 -7
- package/dist/chart/drawers/ht-data-series.drawer.js +1 -1
- package/dist/chart/inputhandlers/hover-producer.component.d.ts +1 -1
- package/dist/chart/inputlisteners/canvas-input-listener.component.d.ts +9 -0
- package/dist/chart/inputlisteners/canvas-input-listener.component.js +38 -1
- package/dist/chart/model/compare-series-hover.d.ts +1 -1
- package/dist/chart/model/compare-series-hover.js +5 -0
- package/dist/chart/model/data-series.model.js +1 -1
- package/dist/chart/model/hit-test-canvas.model.js +2 -2
- package/dist/chart/model/scale.model.d.ts +6 -3
- package/dist/chart/model/scale.model.js +46 -9
- package/dist/chart/model/scaling/constrait.functions.d.ts +1 -1
- package/dist/chart/model/scaling/constrait.functions.js +1 -2
- package/dist/chart/model/scaling/lock-ratio.model.d.ts +8 -2
- package/dist/chart/model/scaling/lock-ratio.model.js +18 -3
- package/dist/chart/model/scaling/viewport.model.d.ts +2 -0
- package/dist/chart/model/scaling/viewport.model.js +13 -4
- package/dist/chart/model/time-zone.model.d.ts +0 -14
- package/dist/chart/model/time-zone.model.js +13 -33
- package/dist/chart/utils/canvas/canvas-drawing-functions.utils.d.ts +12 -1
- package/dist/chart/utils/canvas/canvas-drawing-functions.utils.js +16 -1
- package/dist/chart/utils/canvas/canvas-text-functions.utils.d.ts +3 -2
- package/dist/chart/utils/canvas/canvas-text-functions.utils.js +8 -3
- package/dist/chart/utils/device/touchpad.utils.d.ts +3 -3
- package/dist/chart/utils/device/touchpad.utils.js +3 -5
- package/dist/chart/utils/math.utils.d.ts +1 -1
- package/dist/chart/utils/math.utils.js +4 -1
- package/dist/chart/utils/timezone.utils.d.ts +13 -0
- package/dist/chart/utils/timezone.utils.js +48 -0
- package/dist/dxchart.min.js +6 -6
- package/package.json +1 -2
|
@@ -9,10 +9,9 @@ import { FullChartConfig } from '../chart.config';
|
|
|
9
9
|
export declare class BackgroundDrawer implements Drawer {
|
|
10
10
|
private canvasModel;
|
|
11
11
|
private config;
|
|
12
|
-
|
|
12
|
+
private backgroundDrawPredicate;
|
|
13
|
+
constructor(canvasModel: CanvasModel, config: FullChartConfig, backgroundDrawPredicate?: () => boolean);
|
|
13
14
|
private prevState;
|
|
14
|
-
private prevWidth;
|
|
15
|
-
private prevHeight;
|
|
16
15
|
draw(): void;
|
|
17
16
|
getCanvasIds(): Array<string>;
|
|
18
17
|
}
|
|
@@ -4,39 +4,33 @@
|
|
|
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 { getDPR } from '../utils/device/device-pixel-ratio.utils';
|
|
7
|
-
import { deepEqual } from '../utils/object.utils';
|
|
8
7
|
import { floor } from '../utils/math.utils';
|
|
8
|
+
import { deepEqual } from '../utils/object.utils';
|
|
9
9
|
export class BackgroundDrawer {
|
|
10
|
-
constructor(canvasModel, config) {
|
|
10
|
+
constructor(canvasModel, config, backgroundDrawPredicate = () => true) {
|
|
11
11
|
this.canvasModel = canvasModel;
|
|
12
12
|
this.config = config;
|
|
13
|
+
this.backgroundDrawPredicate = backgroundDrawPredicate;
|
|
13
14
|
// we need to save previous state to avoid unnecessary redraws
|
|
14
15
|
this.prevState = {};
|
|
15
|
-
this.prevWidth = 0;
|
|
16
|
-
this.prevHeight = 0;
|
|
17
16
|
}
|
|
18
17
|
draw() {
|
|
19
|
-
if (deepEqual(this.config.colors.chartAreaTheme, this.prevState)
|
|
20
|
-
this.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
else {
|
|
33
|
-
ctx.fillStyle = this.config.colors.chartAreaTheme.backgroundColor;
|
|
18
|
+
if (this.backgroundDrawPredicate() || !deepEqual(this.config.colors.chartAreaTheme, this.prevState)) {
|
|
19
|
+
this.canvasModel.clear();
|
|
20
|
+
const ctx = this.canvasModel.ctx;
|
|
21
|
+
if (this.config.colors.chartAreaTheme.backgroundMode === 'gradient') {
|
|
22
|
+
const grd = ctx.createLinearGradient(0, 0, this.canvasModel.width, this.canvasModel.height);
|
|
23
|
+
grd.addColorStop(0, this.config.colors.chartAreaTheme.backgroundGradientTopColor);
|
|
24
|
+
grd.addColorStop(1, this.config.colors.chartAreaTheme.backgroundGradientBottomColor);
|
|
25
|
+
ctx.fillStyle = grd;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
ctx.fillStyle = this.config.colors.chartAreaTheme.backgroundColor;
|
|
29
|
+
}
|
|
30
|
+
ctx.fillRect(0, 0, this.canvasModel.width, this.canvasModel.height);
|
|
34
31
|
}
|
|
35
|
-
ctx.fillRect(0, 0, this.canvasModel.width, this.canvasModel.height);
|
|
36
32
|
// save prev state
|
|
37
33
|
this.prevState = Object.assign({}, this.config.colors.chartAreaTheme);
|
|
38
|
-
this.prevWidth = this.canvasModel.width;
|
|
39
|
-
this.prevHeight = this.canvasModel.height;
|
|
40
34
|
}
|
|
41
35
|
getCanvasIds() {
|
|
42
36
|
return [this.canvasModel.canvasId];
|
|
@@ -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 '
|
|
6
|
+
import { clipToBounds } from '../../utils/canvas/canvas-drawing-functions.utils';
|
|
7
7
|
export const candleTypesList = [
|
|
8
8
|
'candle',
|
|
9
9
|
'bar',
|
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { DynamicModelDrawer } from '../components/dynamic-objects/dynamic-objects.drawer';
|
|
7
7
|
import { PaneManager } from '../components/pane/pane-manager.component';
|
|
8
|
-
import { Bounds } from '../model/bounds.model';
|
|
9
8
|
import { CanvasModel } from '../model/canvas.model';
|
|
10
9
|
import { DataSeriesModel, VisualSeriesPoint } from '../model/data-series.model';
|
|
11
10
|
export interface ChartDrawerConfig {
|
|
@@ -33,5 +32,4 @@ export declare class DataSeriesDrawer implements DynamicModelDrawer<DataSeriesMo
|
|
|
33
32
|
draw(canvasModel: CanvasModel, model: DataSeriesModel, paneUUID?: string): void;
|
|
34
33
|
drawSeries(ctx: CanvasRenderingContext2D, series: DataSeriesModel): void;
|
|
35
34
|
}
|
|
36
|
-
export declare const clipToBounds: (ctx: CanvasRenderingContext2D, bounds: Bounds) => void;
|
|
37
35
|
export declare const setLineWidth: (ctx: CanvasRenderingContext2D, lineWidth: number, dataSeries: DataSeriesModel, drawerConfig: ChartDrawerConfig, seriesSelectedWidth?: number) => void;
|
|
@@ -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 { clipToBounds } from '../utils/canvas/canvas-drawing-functions.utils';
|
|
6
7
|
export const transformToTwoDimension = (points) => (Array.isArray(points[0]) ? points : [points]);
|
|
7
8
|
/**
|
|
8
9
|
* Basic data series drawer.
|
|
@@ -42,18 +43,12 @@ export class DataSeriesDrawer {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
export const clipToBounds = (ctx, bounds) => {
|
|
46
|
-
ctx.beginPath();
|
|
47
|
-
ctx.rect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
48
|
-
ctx.clip();
|
|
49
|
-
ctx.closePath();
|
|
50
|
-
};
|
|
51
46
|
export const setLineWidth = (ctx, lineWidth, dataSeries, drawerConfig, seriesSelectedWidth = lineWidth) => {
|
|
52
47
|
if (drawerConfig.forceBold) {
|
|
53
48
|
ctx.lineWidth = drawerConfig.forceBold;
|
|
54
49
|
}
|
|
55
50
|
else if (dataSeries.hovered) {
|
|
56
|
-
ctx.lineWidth = seriesSelectedWidth;
|
|
51
|
+
ctx.lineWidth = lineWidth !== seriesSelectedWidth ? lineWidth + 1 : seriesSelectedWidth;
|
|
57
52
|
}
|
|
58
53
|
else {
|
|
59
54
|
ctx.lineWidth = lineWidth;
|
|
@@ -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 '
|
|
6
|
+
import { clipToBounds } from '../utils/canvas/canvas-drawing-functions.utils';
|
|
7
7
|
/***
|
|
8
8
|
* HitTest Chart drawer. It's used to draw hit test for chart types on the hit-test canvas.
|
|
9
9
|
*/
|
|
@@ -32,7 +32,7 @@ export interface HoverParts {
|
|
|
32
32
|
export interface Hover extends BaseHover, HoverParts {
|
|
33
33
|
}
|
|
34
34
|
export interface HoverProducerPart<T = unknown> {
|
|
35
|
-
getData(hover: BaseHover): T;
|
|
35
|
+
getData(hover: BaseHover): T | undefined;
|
|
36
36
|
}
|
|
37
37
|
export interface HoverProducerParts {
|
|
38
38
|
candleHover: CandleHoverProducerPart;
|
|
@@ -44,6 +44,7 @@ export declare class CanvasInputListenerComponent extends ChartBaseElement {
|
|
|
44
44
|
private mouseUpDocumentSubject;
|
|
45
45
|
private wheelSubject;
|
|
46
46
|
private touchStartSubject;
|
|
47
|
+
private touchStartTimestamp;
|
|
47
48
|
private touchMoveSubject;
|
|
48
49
|
private touchEndSubject;
|
|
49
50
|
private touchCancelSubject;
|
|
@@ -52,6 +53,7 @@ export declare class CanvasInputListenerComponent extends ChartBaseElement {
|
|
|
52
53
|
private contextMenuSubject;
|
|
53
54
|
private pinchSubject;
|
|
54
55
|
private scrollGestureSubject;
|
|
56
|
+
private fastTouchScroll;
|
|
55
57
|
mouseLeavesCanvasSubject: Subject<boolean>;
|
|
56
58
|
dragStartPoint: Point;
|
|
57
59
|
prevDragPoint: Point;
|
|
@@ -312,6 +314,13 @@ export declare class CanvasInputListenerComponent extends ChartBaseElement {
|
|
|
312
314
|
* @returns {Observable<TouchEvent>} - An Observable that emits a TouchEvent when a long touch is detected on the current element.
|
|
313
315
|
*/
|
|
314
316
|
observeLongTouchEnd(hitBoundsTest?: HitBoundsTest): Observable<TouchEvent>;
|
|
317
|
+
/**
|
|
318
|
+
* Returns an Observable that emits a Touch whenever a fast scroll is detected.
|
|
319
|
+
* Fast scroll happens whenever chart or any other pane were moved faster than usual
|
|
320
|
+
* The Observable is created from a Subject that is subscribed to by the component's template.
|
|
321
|
+
* @returns {Observable<TouchEvent>} An Observable that emits a TouchEvent whenever a fast scroll is detected.
|
|
322
|
+
*/
|
|
323
|
+
observeFastTouchScroll(hitBoundsTest?: HitBoundsTest): Observable<TouchEvent>;
|
|
315
324
|
/**
|
|
316
325
|
* Returns the current point of the object.
|
|
317
326
|
* @returns {Point} The current point of the object.
|
|
@@ -46,6 +46,7 @@ class CanvasInputListenerComponent extends ChartBaseElement {
|
|
|
46
46
|
this.mouseUpDocumentSubject = new Subject();
|
|
47
47
|
this.wheelSubject = new Subject();
|
|
48
48
|
this.touchStartSubject = new Subject();
|
|
49
|
+
this.touchStartTimestamp = 0;
|
|
49
50
|
this.touchMoveSubject = new Subject();
|
|
50
51
|
this.touchEndSubject = new Subject();
|
|
51
52
|
this.touchCancelSubject = new Subject();
|
|
@@ -54,6 +55,7 @@ class CanvasInputListenerComponent extends ChartBaseElement {
|
|
|
54
55
|
this.contextMenuSubject = new Subject();
|
|
55
56
|
this.pinchSubject = new Subject();
|
|
56
57
|
this.scrollGestureSubject = new Subject();
|
|
58
|
+
this.fastTouchScroll = new Subject();
|
|
57
59
|
this.mouseLeavesCanvasSubject = new Subject();
|
|
58
60
|
// point at which start dragging
|
|
59
61
|
this.dragStartPoint = { x: 0, y: 0 };
|
|
@@ -236,9 +238,33 @@ class CanvasInputListenerComponent extends ChartBaseElement {
|
|
|
236
238
|
this.element.addEventListener('touchend', touchEndHandler);
|
|
237
239
|
};
|
|
238
240
|
this.addSubscription(subscribeListener(this.element, (e) => longTouchListeners(e), 'touchstart'));
|
|
241
|
+
const fastScrollListenerProducer = (e) => {
|
|
242
|
+
e.preventDefault();
|
|
243
|
+
// should work only if dragged to the left
|
|
244
|
+
if (this.prevDragPoint.x > this.dragStartPoint.x) {
|
|
245
|
+
// in percent, perhaps should be changed to just pixels,
|
|
246
|
+
// because landscape and portait orientations would give different % results
|
|
247
|
+
const minDistance = 35;
|
|
248
|
+
// in ms, should be lower to detect as "fast"
|
|
249
|
+
const maxTime = 250;
|
|
250
|
+
const touchStartTs = this.touchStartTimestamp;
|
|
251
|
+
const touchEndTs = Date.now();
|
|
252
|
+
const time = touchEndTs - touchStartTs;
|
|
253
|
+
const distance = ((this.prevDragPoint.x - this.dragStartPoint.x) / this.canvasBounds.width) * 100;
|
|
254
|
+
const isRightDistance = distance > minDistance;
|
|
255
|
+
const isRightTime = time <= maxTime;
|
|
256
|
+
if (isRightDistance && isRightTime) {
|
|
257
|
+
this.fastTouchScroll.next(e);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
this.addSubscription(subscribeListener(this.element, fastScrollListenerProducer, 'touchend'));
|
|
239
262
|
}
|
|
240
263
|
this.addSubscription(subscribeListener(this.element, leftMouseButtonListener(() => this.dbClickSubject.next(this.currentPoint)), 'dblclick'));
|
|
241
|
-
this.addSubscription(subscribeListener(this.element, (e) =>
|
|
264
|
+
this.addSubscription(subscribeListener(this.element, (e) => {
|
|
265
|
+
this.touchStartSubject.next(e);
|
|
266
|
+
this.touchStartTimestamp = Date.now();
|
|
267
|
+
}, 'touchstart'));
|
|
242
268
|
this.addSubscription(subscribeListener(this.element, (e) => this.touchMoveSubject.next(e), 'touchmove', true));
|
|
243
269
|
this.addSubscription(subscribeListener(this.element, (e) => this.touchEndSubject.next(e), 'touchend'));
|
|
244
270
|
this.addSubscription(subscribeListener(this.element, (e) => this.touchCancelSubject.next(e), 'touchcancel'));
|
|
@@ -643,6 +669,17 @@ class CanvasInputListenerComponent extends ChartBaseElement {
|
|
|
643
669
|
.asObservable()
|
|
644
670
|
.pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)));
|
|
645
671
|
}
|
|
672
|
+
/**
|
|
673
|
+
* Returns an Observable that emits a Touch whenever a fast scroll is detected.
|
|
674
|
+
* Fast scroll happens whenever chart or any other pane were moved faster than usual
|
|
675
|
+
* The Observable is created from a Subject that is subscribed to by the component's template.
|
|
676
|
+
* @returns {Observable<TouchEvent>} An Observable that emits a TouchEvent whenever a fast scroll is detected.
|
|
677
|
+
*/
|
|
678
|
+
observeFastTouchScroll(hitBoundsTest = () => true) {
|
|
679
|
+
return this.fastTouchScroll
|
|
680
|
+
.asObservable()
|
|
681
|
+
.pipe(filter(() => hitBoundsTest(this.currentPoint.x, this.currentPoint.y)));
|
|
682
|
+
}
|
|
646
683
|
/**
|
|
647
684
|
* Returns the current point of the object.
|
|
648
685
|
* @returns {Point} The current point of the object.
|
|
@@ -19,5 +19,5 @@ export declare class CompareSeriesHoverProducerPart implements HoverProducerPart
|
|
|
19
19
|
* @param {BaseHover} hover - The hover object containing the x-coordinate.
|
|
20
20
|
* @returns {CompareSeriesHover[]} An array of objects containing the instrument symbol, price and id of each series of candles.
|
|
21
21
|
*/
|
|
22
|
-
getData(hover: BaseHover): CompareSeriesHover[];
|
|
22
|
+
getData(hover: BaseHover): CompareSeriesHover[] | undefined;
|
|
23
23
|
}
|
|
@@ -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 { MainCandleSeriesModel } from './main-candle-series.model';
|
|
6
7
|
export class CompareSeriesHoverProducerPart {
|
|
7
8
|
constructor(chartModel) {
|
|
8
9
|
this.chartModel = chartModel;
|
|
@@ -13,6 +14,10 @@ export class CompareSeriesHoverProducerPart {
|
|
|
13
14
|
* @returns {CompareSeriesHover[]} An array of objects containing the instrument symbol, price and id of each series of candles.
|
|
14
15
|
*/
|
|
15
16
|
getData(hover) {
|
|
17
|
+
if (this.chartModel.candleSeries.length === 1 &&
|
|
18
|
+
this.chartModel.candleSeries[0] instanceof MainCandleSeriesModel) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
16
21
|
const { x } = hover;
|
|
17
22
|
const candle = this.chartModel.candleFromX(x);
|
|
18
23
|
const idx = candle.idx || 0;
|
|
@@ -138,7 +138,7 @@ export class DataSeriesModel extends ChartBaseElement {
|
|
|
138
138
|
}
|
|
139
139
|
doActivate() {
|
|
140
140
|
this.addRxSubscription(this.scale.xChanged.subscribe(() => this.recalculateDataViewportIndexes()));
|
|
141
|
-
this.addRxSubscription(this.scale.scaleInversedSubject.subscribe(() => this.recalculateVisualPoints()));
|
|
141
|
+
this.addRxSubscription(this.scale.scaleInversedSubject.subscribe(() => { this.recalculateVisualPoints(); }));
|
|
142
142
|
}
|
|
143
143
|
/**
|
|
144
144
|
* Sets the data points and recalculates internal state
|
|
@@ -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, Subject } from 'rxjs';
|
|
6
|
+
import { merge, Subject, animationFrameScheduler } from 'rxjs';
|
|
7
7
|
import { map, throttleTime } from 'rxjs/operators';
|
|
8
8
|
import { CanvasElement } from '../canvas/canvas-bounds-container';
|
|
9
9
|
import { CanvasModel, initCanvasWithConfig } from './canvas.model';
|
|
@@ -50,7 +50,7 @@ export class HitTestCanvasModel extends CanvasModel {
|
|
|
50
50
|
const bounds = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.ALL_PANES);
|
|
51
51
|
const hoverSub = this.canvasInputListener
|
|
52
52
|
.observeMouseMove()
|
|
53
|
-
.pipe(throttleTime(100,
|
|
53
|
+
.pipe(throttleTime(100, animationFrameScheduler, { trailing: true }))
|
|
54
54
|
.subscribe(point => this.eventHandler(point, 'hover'));
|
|
55
55
|
const touchStartSub = this.canvasInputListener
|
|
56
56
|
.observeTouchStart()
|
|
@@ -48,6 +48,8 @@ export declare class ScaleModel extends ViewportModel {
|
|
|
48
48
|
xConstraints: Constraints[];
|
|
49
49
|
readonly state: ChartScale;
|
|
50
50
|
constructor(config: FullChartConfig, getBounds: BoundsProvider, canvasAnimation: CanvasAnimation);
|
|
51
|
+
protected doActivate(): void;
|
|
52
|
+
protected doDeactivate(): void;
|
|
51
53
|
/**
|
|
52
54
|
* The method adds a new "constraint" to the existing list of x-axis constraints for charting.
|
|
53
55
|
* The "constraint" is expected to be an object containing information about the constraints, such as the minimum and maximum values for the x-axis.
|
|
@@ -71,13 +73,13 @@ export declare class ScaleModel extends ViewportModel {
|
|
|
71
73
|
* @param forceNoAnimation Whether to skip animation.
|
|
72
74
|
* @param zoomSensitivity The sensitivity of the zoom.
|
|
73
75
|
*/
|
|
74
|
-
zoomXToPercent(viewportPercent: ViewportPercent, zoomIn: boolean, forceNoAnimation
|
|
76
|
+
zoomXToPercent(viewportPercent: ViewportPercent, zoomIn: boolean, forceNoAnimation: boolean | undefined, zoomSensitivity: number): void;
|
|
75
77
|
/**
|
|
76
78
|
* Zooms the X axis of the chart relativly to the end of the data range.
|
|
77
79
|
* @param zoomIn - If true, the chart will be zoomed in. If false, the chart will be zoomed out.
|
|
78
80
|
* @param zoomSensitivity - The sensitivity of the zoom. Default value is taken from the configuration object.
|
|
79
81
|
*/
|
|
80
|
-
zoomXToEnd(zoomIn: boolean, zoomSensitivity
|
|
82
|
+
zoomXToEnd(zoomIn: boolean, zoomSensitivity: number): void;
|
|
81
83
|
haltAnimation(): void;
|
|
82
84
|
private zoomXTo;
|
|
83
85
|
/**
|
|
@@ -88,7 +90,8 @@ export declare class ScaleModel extends ViewportModel {
|
|
|
88
90
|
* @param fireChanged
|
|
89
91
|
* @param forceNoAutoScale - force NOT apply auto-scaling (for lazy loading)
|
|
90
92
|
*/
|
|
91
|
-
setXScale(xStart: Unit, xEnd: Unit): void;
|
|
93
|
+
setXScale(xStart: Unit, xEnd: Unit, forceNoAnimation?: boolean): void;
|
|
94
|
+
setYScale(yStart: Unit, yEnd: Unit, fire?: boolean): void;
|
|
92
95
|
/**
|
|
93
96
|
* Moves both xStart and xEnd without changing the viewport width (zoom).
|
|
94
97
|
* Works without animation.
|
|
@@ -8,7 +8,7 @@ import { startViewportModelAnimation } from '../animation/viewport-model-animati
|
|
|
8
8
|
import { cloneUnsafe } from '../utils/object.utils';
|
|
9
9
|
import { AutoScaleViewportSubModel } from './scaling/auto-scale.model';
|
|
10
10
|
import { zoomConstraint } from './scaling/constrait.functions';
|
|
11
|
-
import {
|
|
11
|
+
import { changeXToKeepRatio, changeYToKeepRatio, ratioFromZoomXY } from './scaling/lock-ratio.model';
|
|
12
12
|
import { moveXStart, moveYStart } from './scaling/move-chart.functions';
|
|
13
13
|
import { ViewportModel, compareStates } from './scaling/viewport.model';
|
|
14
14
|
import { zoomXToEndViewportCalculator, zoomXToPercentViewportCalculator } from './scaling/x-zooming.functions';
|
|
@@ -51,6 +51,19 @@ export class ScaleModel extends ViewportModel {
|
|
|
51
51
|
this.offsets = this.config.components.offsets;
|
|
52
52
|
this.addXConstraint((initialState, state) => zoomConstraint(initialState, state, this.config.components.chart, this.getBounds));
|
|
53
53
|
}
|
|
54
|
+
doActivate() {
|
|
55
|
+
super.doActivate();
|
|
56
|
+
this.scaleInversedSubject = new Subject();
|
|
57
|
+
this.beforeStartAnimationSubject = new Subject();
|
|
58
|
+
this.addRxSubscription(this.scaleInversedSubject.subscribe(() => {
|
|
59
|
+
this.fireChanged();
|
|
60
|
+
}));
|
|
61
|
+
}
|
|
62
|
+
doDeactivate() {
|
|
63
|
+
super.doDeactivate();
|
|
64
|
+
this.scaleInversedSubject.complete();
|
|
65
|
+
this.beforeStartAnimationSubject.complete();
|
|
66
|
+
}
|
|
54
67
|
/**
|
|
55
68
|
* The method adds a new "constraint" to the existing list of x-axis constraints for charting.
|
|
56
69
|
* The "constraint" is expected to be an object containing information about the constraints, such as the minimum and maximum values for the x-axis.
|
|
@@ -81,7 +94,7 @@ export class ScaleModel extends ViewportModel {
|
|
|
81
94
|
* @param forceNoAnimation Whether to skip animation.
|
|
82
95
|
* @param zoomSensitivity The sensitivity of the zoom.
|
|
83
96
|
*/
|
|
84
|
-
zoomXToPercent(viewportPercent, zoomIn, forceNoAnimation = false, zoomSensitivity
|
|
97
|
+
zoomXToPercent(viewportPercent, zoomIn, forceNoAnimation = false, zoomSensitivity) {
|
|
85
98
|
const disabledAnimations = this.config.scale.disableAnimations || forceNoAnimation;
|
|
86
99
|
if (disabledAnimations) {
|
|
87
100
|
this.haltAnimation();
|
|
@@ -96,7 +109,7 @@ export class ScaleModel extends ViewportModel {
|
|
|
96
109
|
* @param zoomIn - If true, the chart will be zoomed in. If false, the chart will be zoomed out.
|
|
97
110
|
* @param zoomSensitivity - The sensitivity of the zoom. Default value is taken from the configuration object.
|
|
98
111
|
*/
|
|
99
|
-
zoomXToEnd(zoomIn, zoomSensitivity
|
|
112
|
+
zoomXToEnd(zoomIn, zoomSensitivity) {
|
|
100
113
|
if (this.config.scale.disableAnimations) {
|
|
101
114
|
this.haltAnimation();
|
|
102
115
|
}
|
|
@@ -116,7 +129,7 @@ export class ScaleModel extends ViewportModel {
|
|
|
116
129
|
const initialStateCopy = Object.assign({}, state);
|
|
117
130
|
const constrainedState = this.scalePostProcessor(initialStateCopy, state);
|
|
118
131
|
if (this.state.lockPriceToBarRatio) {
|
|
119
|
-
|
|
132
|
+
changeYToKeepRatio(constrainedState, this.zoomXYRatio);
|
|
120
133
|
}
|
|
121
134
|
if (this.state.auto) {
|
|
122
135
|
this.autoScaleModel.doAutoYScale(constrainedState);
|
|
@@ -136,18 +149,42 @@ export class ScaleModel extends ViewportModel {
|
|
|
136
149
|
* @param fireChanged
|
|
137
150
|
* @param forceNoAutoScale - force NOT apply auto-scaling (for lazy loading)
|
|
138
151
|
*/
|
|
139
|
-
setXScale(xStart, xEnd) {
|
|
152
|
+
setXScale(xStart, xEnd, forceNoAnimation = true) {
|
|
140
153
|
const initialState = this.export();
|
|
141
|
-
|
|
142
|
-
const state =
|
|
154
|
+
const zoomX = this.calculateZoomX(xStart, xEnd);
|
|
155
|
+
const state = Object.assign(Object.assign({}, initialState), { zoomX, xStart, xEnd });
|
|
143
156
|
const constrainedState = this.scalePostProcessor(initialState, state);
|
|
144
157
|
if (this.state.lockPriceToBarRatio) {
|
|
145
|
-
|
|
158
|
+
changeYToKeepRatio(constrainedState, this.zoomXYRatio);
|
|
146
159
|
}
|
|
147
160
|
if (this.state.auto) {
|
|
148
161
|
this.autoScaleModel.doAutoYScale(constrainedState);
|
|
149
162
|
}
|
|
150
|
-
this.
|
|
163
|
+
if (forceNoAnimation || this.config.scale.disableAnimations) {
|
|
164
|
+
this.haltAnimation();
|
|
165
|
+
this.apply(constrainedState);
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
startViewportModelAnimation(this.canvasAnimation, this, constrainedState);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
setYScale(yStart, yEnd, fire = false) {
|
|
172
|
+
const initialState = this.export();
|
|
173
|
+
super.setYScale(yStart, yEnd, fire);
|
|
174
|
+
const state = this.export();
|
|
175
|
+
const constrainedState = this.scalePostProcessor(initialState, state);
|
|
176
|
+
if (this.state.lockPriceToBarRatio) {
|
|
177
|
+
changeXToKeepRatio(constrainedState, this.zoomXYRatio);
|
|
178
|
+
this.setXScale(constrainedState.xStart, constrainedState.xEnd);
|
|
179
|
+
// TODO: rewrite logic for applying constraints to consider both axes, now constraints on Y may not work correctly
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
if (this.state.auto) {
|
|
184
|
+
this.autoScaleModel.doAutoYScale(constrainedState);
|
|
185
|
+
}
|
|
186
|
+
this.apply(constrainedState);
|
|
187
|
+
}
|
|
151
188
|
}
|
|
152
189
|
/**
|
|
153
190
|
* Moves both xStart and xEnd without changing the viewport width (zoom).
|
|
@@ -32,7 +32,7 @@ export declare const candleEdgesConstrait: (state: ViewportModelState, visualCan
|
|
|
32
32
|
* @returns
|
|
33
33
|
* @doc-tags viewport,zoom,scaling
|
|
34
34
|
*/
|
|
35
|
-
export declare const zoomConstraint: (
|
|
35
|
+
export declare const zoomConstraint: (_: ViewportModelState, state: ViewportModelState, chartConfig: ChartConfigComponentsChart, boundsProvider: BoundsProvider) => {
|
|
36
36
|
xStart: number;
|
|
37
37
|
xEnd: number;
|
|
38
38
|
yStart: number;
|
|
@@ -40,7 +40,7 @@ export const candleEdgesConstrait = (state, visualCandlesCoordinates, candleLimi
|
|
|
40
40
|
* @returns
|
|
41
41
|
* @doc-tags viewport,zoom,scaling
|
|
42
42
|
*/
|
|
43
|
-
export const zoomConstraint = (
|
|
43
|
+
export const zoomConstraint = (_, state, chartConfig, boundsProvider) => {
|
|
44
44
|
const newState = Object.assign({}, state);
|
|
45
45
|
const bounds = boundsProvider();
|
|
46
46
|
// 1 - is an average candle width: newXEnd - newXStart = avg candles amount in the viewport
|
|
@@ -56,7 +56,6 @@ export const zoomConstraint = (initialState, state, chartConfig, boundsProvider)
|
|
|
56
56
|
return newState;
|
|
57
57
|
}
|
|
58
58
|
if (minViewportReached) {
|
|
59
|
-
newState.xEnd = initialState.xEnd;
|
|
60
59
|
newState.xStart = newState.xEnd - chartConfig.minCandles;
|
|
61
60
|
newState.zoomX = calculateZoom(newState.xEnd - newState.xStart, bounds.width);
|
|
62
61
|
return newState;
|
|
@@ -9,8 +9,14 @@ export declare const ratioFromZoomXY: (zoomX: Zoom, zoomY: Zoom) => ZoomXToZoomY
|
|
|
9
9
|
export declare const zoomXToZoomY: (zoomX: Zoom, ratio: ZoomXToZoomYRatio) => Zoom;
|
|
10
10
|
export declare const zoomYToZoomX: (zoomY: Zoom, ratio: ZoomXToZoomYRatio) => Zoom;
|
|
11
11
|
/**
|
|
12
|
-
* Locks the zoomY with zoomX and
|
|
12
|
+
* Locks the zoomY with zoomX and zooms y-scale depending on x-scale.
|
|
13
13
|
* @param state
|
|
14
14
|
* @param zoomXYRatio
|
|
15
15
|
*/
|
|
16
|
-
export declare const
|
|
16
|
+
export declare const changeYToKeepRatio: (state: ViewportModelState, zoomXYRatio: ZoomXToZoomYRatio) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Locks the zoomY with zoomX and zooms x-scale depending on y-scale.
|
|
19
|
+
* @param state
|
|
20
|
+
* @param zoomXYRatio
|
|
21
|
+
*/
|
|
22
|
+
export declare const changeXToKeepRatio: (state: ViewportModelState, zoomXYRatio: ZoomXToZoomYRatio) => void;
|
|
@@ -7,16 +7,31 @@ export const ratioFromZoomXY = (zoomX, zoomY) => zoomX / zoomY;
|
|
|
7
7
|
export const zoomXToZoomY = (zoomX, ratio) => zoomX / ratio;
|
|
8
8
|
export const zoomYToZoomX = (zoomY, ratio) => zoomY * ratio;
|
|
9
9
|
/**
|
|
10
|
-
* Locks the zoomY with zoomX and
|
|
10
|
+
* Locks the zoomY with zoomX and zooms y-scale depending on x-scale.
|
|
11
11
|
* @param state
|
|
12
12
|
* @param zoomXYRatio
|
|
13
13
|
*/
|
|
14
|
-
export const
|
|
14
|
+
export const changeYToKeepRatio = (state, zoomXYRatio) => {
|
|
15
15
|
const prevZoomY = state.zoomY;
|
|
16
16
|
state.zoomY = zoomXToZoomY(state.zoomX, zoomXYRatio);
|
|
17
17
|
const zoomYMult = state.zoomY / prevZoomY;
|
|
18
18
|
const lastYHeight = state.yEnd - state.yStart;
|
|
19
19
|
const newYHeight = lastYHeight * zoomYMult;
|
|
20
20
|
const delta = newYHeight - lastYHeight;
|
|
21
|
-
state.yEnd = state.yEnd + delta;
|
|
21
|
+
state.yEnd = state.yEnd + delta / 2;
|
|
22
|
+
state.yStart = state.yStart - delta / 2;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Locks the zoomY with zoomX and zooms x-scale depending on y-scale.
|
|
26
|
+
* @param state
|
|
27
|
+
* @param zoomXYRatio
|
|
28
|
+
*/
|
|
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;
|
|
22
37
|
};
|
|
@@ -92,6 +92,8 @@ export declare abstract class ViewportModel extends ChartBaseElement implements
|
|
|
92
92
|
start: number;
|
|
93
93
|
end: number;
|
|
94
94
|
}>;
|
|
95
|
+
protected doActivate(): void;
|
|
96
|
+
protected doDeactivate(): void;
|
|
95
97
|
/**
|
|
96
98
|
* Converts a unit value to pixels based on the current zoom level and xStart value.
|
|
97
99
|
* @param {Unit} unit - The unit value to be converted to pixels.
|
|
@@ -52,6 +52,13 @@ export class ViewportModel extends ChartBaseElement {
|
|
|
52
52
|
})), distinctUntilChanged((p, c) => p.start === c.start && p.end === c.end), share());
|
|
53
53
|
}
|
|
54
54
|
//endregion
|
|
55
|
+
doActivate() {
|
|
56
|
+
super.doActivate();
|
|
57
|
+
}
|
|
58
|
+
doDeactivate() {
|
|
59
|
+
super.doDeactivate();
|
|
60
|
+
this.changed.complete();
|
|
61
|
+
}
|
|
55
62
|
//region conversion methods
|
|
56
63
|
/**
|
|
57
64
|
* Converts a unit value to pixels based on the current zoom level and xStart value.
|
|
@@ -75,12 +82,13 @@ export class ViewportModel extends ChartBaseElement {
|
|
|
75
82
|
* @returns {Pixel} - The pixel value of the given unit value in the Y-axis.
|
|
76
83
|
*/
|
|
77
84
|
toY(unit) {
|
|
85
|
+
const bounds = this.getBounds();
|
|
78
86
|
if (this.inverseY) {
|
|
79
|
-
return
|
|
87
|
+
return bounds.y + unitToPixels(unit - this.yStart, this.zoomY);
|
|
80
88
|
}
|
|
81
89
|
else {
|
|
82
90
|
// inverse by default because canvas calculation [0,0] point starts from top-left corner
|
|
83
|
-
return
|
|
91
|
+
return bounds.y + bounds.height - unitToPixels(unit - this.yStart, this.zoomY);
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
94
|
/**
|
|
@@ -106,13 +114,14 @@ export class ViewportModel extends ChartBaseElement {
|
|
|
106
114
|
* @returns {void}
|
|
107
115
|
*/
|
|
108
116
|
fromY(px) {
|
|
109
|
-
const
|
|
117
|
+
const bounds = this.getBounds();
|
|
118
|
+
const normalizedPx = px - bounds.y;
|
|
110
119
|
if (this.inverseY) {
|
|
111
120
|
return pixelsToUnits(normalizedPx + unitToPixels(this.yStart, this.zoomY), this.zoomY);
|
|
112
121
|
}
|
|
113
122
|
else {
|
|
114
123
|
// inverse by default because canvas calculation [0,0] point starts from top-left corner
|
|
115
|
-
return pixelsToUnits(
|
|
124
|
+
return pixelsToUnits(bounds.height - normalizedPx + unitToPixels(this.yStart, this.zoomY), this.zoomY);
|
|
116
125
|
}
|
|
117
126
|
}
|
|
118
127
|
//endregion
|
|
@@ -3,7 +3,6 @@
|
|
|
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 { getTimezoneOffset as getTimezoneOffsetDateFnsTz } from 'date-fns-tz';
|
|
7
6
|
import { Observable } from 'rxjs';
|
|
8
7
|
import { DateFormatter, FullChartConfig } from '../chart.config';
|
|
9
8
|
import { DateTimeFormatter, DateTimeFormatterFactory } from './date-time.formatter';
|
|
@@ -13,8 +12,6 @@ export interface TimeZone {
|
|
|
13
12
|
readonly name: string;
|
|
14
13
|
readonly utcOffset: string;
|
|
15
14
|
}
|
|
16
|
-
export declare const memoizedTZOffset: typeof getTimezoneOffsetDateFnsTz;
|
|
17
|
-
export declare const getTimezoneOffset: (timezone: string, time: Timestamp) => number;
|
|
18
15
|
export declare class TimeZoneModel {
|
|
19
16
|
private config;
|
|
20
17
|
private timeZoneChangedSubject;
|
|
@@ -50,16 +47,5 @@ export declare class TimeZoneModel {
|
|
|
50
47
|
getFormatterFactory(): DateTimeFormatterFactory;
|
|
51
48
|
private formatterCache;
|
|
52
49
|
getDateTimeFormatter(format: string): DateTimeFormatter;
|
|
53
|
-
/**
|
|
54
|
-
* Calculates the offset of a given timezone from the local timezone.
|
|
55
|
-
* @private
|
|
56
|
-
* @param {string} timezone - The timezone to calculate the offset for.
|
|
57
|
-
*/
|
|
58
|
-
private getOffset;
|
|
59
|
-
/**
|
|
60
|
-
* Gets the timezone offset value in milliseconds
|
|
61
|
-
* @param {string} timezone name
|
|
62
|
-
* @returns {function(time:Number):Date}
|
|
63
|
-
*/
|
|
64
50
|
tzOffset(timezone: string): (time: number) => Date;
|
|
65
51
|
}
|