@devexperts/dxcharts-lite 2.7.28 → 2.7.30
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 +1 -1
- package/dist/chart/components/chart/chart-area-pan.handler.d.ts +6 -0
- package/dist/chart/components/chart/chart-area-pan.handler.js +9 -3
- package/dist/chart/components/cross_tool/cross-tool.model.d.ts +1 -0
- package/dist/chart/components/cross_tool/cross-tool.model.js +8 -1
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop-x.component.d.ts +6 -1
- package/dist/chart/components/dran-n-drop_helper/drag-n-drop-x.component.js +25 -2
- package/dist/chart/components/pane/pane.component.js +9 -2
- package/dist/chart/components/x_axis/x-axis-scale.handler.d.ts +6 -0
- package/dist/chart/components/x_axis/x-axis-scale.handler.js +10 -2
- package/dist/chart/components/x_axis/x-axis.component.d.ts +3 -1
- package/dist/chart/components/x_axis/x-axis.component.js +8 -2
- package/dist/chart/components/y_axis/price_labels/price-label.drawer.js +1 -1
- package/dist/chart/components/y_axis/price_labels/y-axis-labels.model.js +6 -3
- package/dist/chart/components/y_axis/y-axis-labels.drawer.d.ts +8 -1
- package/dist/chart/components/y_axis/y-axis-labels.drawer.js +1 -1
- package/dist/chart/inputhandlers/hover-producer.component.d.ts +4 -0
- package/dist/chart/inputhandlers/hover-producer.component.js +47 -14
- package/dist/chart/model/scale.model.d.ts +2 -6
- package/dist/chart/model/scaling/viewport.model.d.ts +2 -0
- package/dist/chart/utils/__tests__/canvas-lower-hover-strip.utils.test.d.ts +6 -0
- package/dist/chart/utils/__tests__/canvas-lower-hover-strip.utils.test.js +34 -0
- package/dist/chart/utils/canvas/canvas-drawing-functions.utils.d.ts +1 -1
- package/dist/chart/utils/canvas/canvas-drawing-functions.utils.js +4 -1
- package/dist/chart/utils/canvas-lower-hover-strip.utils.d.ts +17 -0
- package/dist/chart/utils/canvas-lower-hover-strip.utils.js +20 -0
- package/dist/dxchart.min.js +4 -4
- package/package.json +14 -14
package/dist/chart/bootstrap.js
CHANGED
|
@@ -161,7 +161,7 @@ export default class ChartBootstrap {
|
|
|
161
161
|
this.canvasBoundsContainer.setMainCandleSeries(this.chartModel.mainCandleSeries);
|
|
162
162
|
hitTestCanvasModel.addSubscriber(paneManager.hitTestController);
|
|
163
163
|
// X-axis component
|
|
164
|
-
this.xAxisComponent = new XAxisComponent(eventBus, config, mainCanvasModel, chartComponent, scaleModel, canvasBoundsContainer, canvasInputListener, chartResizeHandler, this.drawingManager, timeZoneModel, chartPanComponent, this.cursorHandler, this.hitTestCanvasModel);
|
|
164
|
+
this.xAxisComponent = new XAxisComponent(eventBus, config, mainCanvasModel, chartComponent, scaleModel, canvasBoundsContainer, canvasInputListener, chartResizeHandler, this.drawingManager, timeZoneModel, chartPanComponent, this.cursorHandler, this.hitTestCanvasModel, this.mainPane.yAxis);
|
|
165
165
|
this.chartComponents.push(this.xAxisComponent);
|
|
166
166
|
this.userInputListenerComponents.push(this.xAxisComponent.xAxisScaleHandler);
|
|
167
167
|
const mainCanvasClearDrawer = new ClearCanvasDrawer(mainCanvasModel);
|
|
@@ -10,6 +10,7 @@ import EventBus from '../../events/event-bus';
|
|
|
10
10
|
import { CanvasInputListenerComponent, Point } from '../../inputlisteners/canvas-input-listener.component';
|
|
11
11
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
12
12
|
import { ScaleModel } from '../../model/scale.model';
|
|
13
|
+
import { DragNDropXComponent } from '../dran-n-drop_helper/drag-n-drop-x.component';
|
|
13
14
|
import { DragNDropYComponent } from '../dran-n-drop_helper/drag-n-drop-y.component';
|
|
14
15
|
import { DragInfo } from '../dran-n-drop_helper/drag-n-drop.component';
|
|
15
16
|
import { ChartPanComponent } from '../pan/chart-pan.component';
|
|
@@ -53,7 +54,12 @@ export declare class ChartAreaPanHandler extends ChartBaseElement {
|
|
|
53
54
|
lastXStart: number;
|
|
54
55
|
wheelThrottleTime: number;
|
|
55
56
|
chartPanningOptions: ChartPanningOptions;
|
|
57
|
+
dragNDropXComponent: DragNDropXComponent;
|
|
56
58
|
constructor(bus: EventBus, config: FullChartConfig, scale: ScaleModel, canvasInputListener: CanvasInputListenerComponent, canvasBoundsContainer: CanvasBoundsContainer, canvasAnimation: CanvasAnimation, chartPanComponent: ChartPanComponent, hitTestCanvasModel: HitTestCanvasModel);
|
|
59
|
+
/**
|
|
60
|
+
* Throttles chart-area horizontal drag to one animation frame when needed (percent Y-axis).
|
|
61
|
+
*/
|
|
62
|
+
setChartAreaXDragThrottled(shouldThrottle: boolean): void;
|
|
57
63
|
/**
|
|
58
64
|
* It observes the wheel event on all panes of the canvas and throttles it to the specified time.
|
|
59
65
|
* It then calculates the zoom sensitivity based on whether the event was triggered by a touchpad or not.
|
|
@@ -99,16 +99,22 @@ export class ChartAreaPanHandler extends ChartBaseElement {
|
|
|
99
99
|
};
|
|
100
100
|
const allPanesHitTest = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.ALL_PANES);
|
|
101
101
|
//#region drag-n-drop logic
|
|
102
|
-
|
|
102
|
+
this.dragNDropXComponent = new DragNDropXComponent(allPanesHitTest, {
|
|
103
103
|
onDragStart: this.onXDragStart,
|
|
104
104
|
onDragTick: this.onXDragTick,
|
|
105
105
|
onDragEnd: this.onXDragEnd,
|
|
106
106
|
}, this.canvasInputListener, this.chartPanComponent, {
|
|
107
107
|
dragPredicate: () => this.chartPanningOptions.horizontal,
|
|
108
|
-
});
|
|
109
|
-
this.addChildEntity(dragNDropXComponent);
|
|
108
|
+
}, this.config.components.yAxis.type === 'percent');
|
|
109
|
+
this.addChildEntity(this.dragNDropXComponent);
|
|
110
110
|
//#endregion
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* Throttles chart-area horizontal drag to one animation frame when needed (percent Y-axis).
|
|
114
|
+
*/
|
|
115
|
+
setChartAreaXDragThrottled(shouldThrottle) {
|
|
116
|
+
this.dragNDropXComponent.setShouldThrottle(shouldThrottle);
|
|
117
|
+
}
|
|
112
118
|
/**
|
|
113
119
|
* This method is used to activate the zoom functionality of the canvas. It extends the doActivate method of the parent class.
|
|
114
120
|
* @protected
|
|
@@ -38,6 +38,7 @@ export declare class CrossToolModel extends ChartBaseElement {
|
|
|
38
38
|
* @returns {void}
|
|
39
39
|
*/
|
|
40
40
|
setType(type: CrossToolType): void;
|
|
41
|
+
private shouldKeepXForMobileTouchCrosshair;
|
|
41
42
|
/**
|
|
42
43
|
* Method to activate the cross tool.
|
|
43
44
|
* It subscribes to the hoverProducer's hover event and updates the crosstool.
|
|
@@ -35,6 +35,11 @@ export class CrossToolModel extends ChartBaseElement {
|
|
|
35
35
|
setType(type) {
|
|
36
36
|
this.config.type = type;
|
|
37
37
|
}
|
|
38
|
+
shouldKeepXForMobileTouchCrosshair() {
|
|
39
|
+
return (isMobile() &&
|
|
40
|
+
this.hoverProducer.longTouchActivatedSubject.getValue() &&
|
|
41
|
+
this.crossEventProducer.crossSubject.getValue() !== null);
|
|
42
|
+
}
|
|
38
43
|
/**
|
|
39
44
|
* Method to activate the cross tool.
|
|
40
45
|
* It subscribes to the hoverProducer's hover event and updates the crosstool.
|
|
@@ -100,7 +105,9 @@ export class CrossToolModel extends ChartBaseElement {
|
|
|
100
105
|
*/
|
|
101
106
|
updateCrossTool(hover, magnetTarget = this.config.magnetTarget, discrete = this.config.discrete) {
|
|
102
107
|
var _a;
|
|
103
|
-
const x = discrete
|
|
108
|
+
const x = discrete && !this.shouldKeepXForMobileTouchCrosshair()
|
|
109
|
+
? this.chartModel.toX((_a = this.chartModel.candleFromX(hover.x, true).idx) !== null && _a !== void 0 ? _a : 0)
|
|
110
|
+
: hover.x;
|
|
104
111
|
if (this.currentHover === null) {
|
|
105
112
|
this.currentHover = { x, y: 0, time: hover.timeFormatted, paneId: hover.paneId };
|
|
106
113
|
}
|
|
@@ -8,7 +8,12 @@ import { CanvasInputListenerComponent } from '../../inputlisteners/canvas-input-
|
|
|
8
8
|
import { ChartPanComponent } from '../pan/chart-pan.component';
|
|
9
9
|
import { DragComponentOptions, DragNDropComponent, DragNDropComponentCallbacks } from './drag-n-drop.component';
|
|
10
10
|
export declare class DragNDropXComponent extends DragNDropComponent {
|
|
11
|
-
|
|
11
|
+
private shouldThrottleSubject;
|
|
12
|
+
constructor(hitTest: HitBoundsTest, dragCallbacks: DragNDropComponentCallbacks, canvasInputListener: CanvasInputListenerComponent, chartPanComponent: ChartPanComponent, dragComponentOptions?: DragComponentOptions, shouldThrottle?: boolean);
|
|
13
|
+
/**
|
|
14
|
+
* When true, X drag ticks are throttled to one animation frame (e.g. percent axis).
|
|
15
|
+
*/
|
|
16
|
+
setShouldThrottle(value: boolean): void;
|
|
12
17
|
/**
|
|
13
18
|
* This method is used to activate the component and add the necessary subscriptions to the canvasInputListener.
|
|
14
19
|
* It calls the super method doActivate() and then adds the following subscriptions:
|
|
@@ -3,10 +3,25 @@
|
|
|
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
|
+
/*
|
|
7
|
+
* Copyright (C) 2019 - 2024 Devexperts Solutions IE Limited
|
|
8
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
9
|
+
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
10
|
+
*/
|
|
11
|
+
import { animationFrameScheduler, BehaviorSubject, identity } from 'rxjs';
|
|
12
|
+
import { distinctUntilChanged, switchMap, throttleTime } from 'rxjs/operators';
|
|
6
13
|
import { defaultDragComponentOptions, DragNDropComponent, } from './drag-n-drop.component';
|
|
14
|
+
import { ONE_FRAME_MS } from '../../utils/numeric-constants.utils';
|
|
7
15
|
export class DragNDropXComponent extends DragNDropComponent {
|
|
8
|
-
constructor(hitTest, dragCallbacks, canvasInputListener, chartPanComponent, dragComponentOptions = defaultDragComponentOptions) {
|
|
16
|
+
constructor(hitTest, dragCallbacks, canvasInputListener, chartPanComponent, dragComponentOptions = defaultDragComponentOptions, shouldThrottle) {
|
|
9
17
|
super(hitTest, dragCallbacks, canvasInputListener, chartPanComponent, dragComponentOptions);
|
|
18
|
+
this.shouldThrottleSubject = new BehaviorSubject(!!shouldThrottle);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* When true, X drag ticks are throttled to one animation frame (e.g. percent axis).
|
|
22
|
+
*/
|
|
23
|
+
setShouldThrottle(value) {
|
|
24
|
+
this.shouldThrottleSubject.next(value);
|
|
10
25
|
}
|
|
11
26
|
/**
|
|
12
27
|
* This method is used to activate the component and add the necessary subscriptions to the canvasInputListener.
|
|
@@ -17,9 +32,17 @@ export class DragNDropXComponent extends DragNDropComponent {
|
|
|
17
32
|
* @returns {void}
|
|
18
33
|
*/
|
|
19
34
|
doActivate() {
|
|
35
|
+
const dragThrottleTime = ONE_FRAME_MS;
|
|
20
36
|
super.doActivate();
|
|
21
37
|
this.addRxSubscription(this.canvasInputListener.observeXDragStart(this.hitTest).subscribe(this.onDragStart));
|
|
22
|
-
this.addRxSubscription(this.
|
|
38
|
+
this.addRxSubscription(this.shouldThrottleSubject
|
|
39
|
+
.pipe(distinctUntilChanged(), switchMap(shouldThrottle => this.canvasInputListener.observeXDrag().pipe(shouldThrottle
|
|
40
|
+
? throttleTime(dragThrottleTime, animationFrameScheduler, {
|
|
41
|
+
trailing: true,
|
|
42
|
+
leading: true,
|
|
43
|
+
})
|
|
44
|
+
: identity)))
|
|
45
|
+
.subscribe(this.onDragTick));
|
|
23
46
|
this.addRxSubscription(this.canvasInputListener.observeXDragEnd().subscribe(this.onDragEnd));
|
|
24
47
|
}
|
|
25
48
|
}
|
|
@@ -4,8 +4,8 @@
|
|
|
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 { Subject } from 'rxjs';
|
|
7
|
-
import { distinctUntilChanged } from 'rxjs/operators';
|
|
8
|
-
import { areBoundsChanged, CanvasElement, } from '../../canvas/canvas-bounds-container';
|
|
7
|
+
import { distinctUntilChanged, map, startWith } from 'rxjs/operators';
|
|
8
|
+
import { areBoundsChanged, CHART_UUID, CanvasElement, } from '../../canvas/canvas-bounds-container';
|
|
9
9
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
10
10
|
import { SyncedByXScaleModel } from '../../model/scale.model';
|
|
11
11
|
import { firstOf, flatMap, lastOf } from '../../utils/array.utils';
|
|
@@ -80,6 +80,13 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
80
80
|
this.yExtentComponents.forEach(c => c.scale.recalculateZoomY());
|
|
81
81
|
this.dynamicObjectsCanvasModel.fireDraw();
|
|
82
82
|
}));
|
|
83
|
+
if (this.uuid === CHART_UUID) {
|
|
84
|
+
this.addRxSubscription(this.yAxis.axisTypeSetSubject
|
|
85
|
+
.pipe(startWith(this.yAxis.getAxisType()), distinctUntilChanged(), map((axisType) => axisType === 'percent'))
|
|
86
|
+
.subscribe(shouldThrottle => {
|
|
87
|
+
this.chartPanComponent.chartAreaPanHandler.setChartAreaXDragThrottled(shouldThrottle);
|
|
88
|
+
}));
|
|
89
|
+
}
|
|
83
90
|
}
|
|
84
91
|
toY(price) {
|
|
85
92
|
var _a, _b;
|
|
@@ -9,6 +9,7 @@ import { CanvasInputListenerComponent } from '../../inputlisteners/canvas-input-
|
|
|
9
9
|
import { ScaleModel } from '../../model/scale.model';
|
|
10
10
|
import { Pixel, Unit } from '../../model/scaling/viewport.model';
|
|
11
11
|
import { ChartModel } from '../chart/chart.model';
|
|
12
|
+
import { DragNDropXComponent } from '../dran-n-drop_helper/drag-n-drop-x.component';
|
|
12
13
|
import { ChartPanComponent } from '../pan/chart-pan.component';
|
|
13
14
|
import { HitTestCanvasModel } from '../../model/hit-test-canvas.model';
|
|
14
15
|
/**
|
|
@@ -30,7 +31,12 @@ export declare class XAxisScaleHandler extends ChartBaseElement {
|
|
|
30
31
|
private dblClickCallback;
|
|
31
32
|
private touches;
|
|
32
33
|
private dblTapCallback;
|
|
34
|
+
dragNDropXComponent: DragNDropXComponent;
|
|
33
35
|
constructor(scale: ScaleModel, canvasInputListener: CanvasInputListenerComponent, canvasBoundsContainer: CanvasBoundsContainer, chartPanComponent: ChartPanComponent, chartModel: ChartModel, hitTest: HitBoundsTest, hitTestCanvasModel: HitTestCanvasModel);
|
|
36
|
+
/**
|
|
37
|
+
* Throttles chart-area horizontal drag to one animation frame when needed (percent Y-axis).
|
|
38
|
+
*/
|
|
39
|
+
setChartAreaXDragThrottled(shouldThrottle: boolean): void;
|
|
34
40
|
/**
|
|
35
41
|
* This method is used to activate the canvas input listener and add a subscription to it.
|
|
36
42
|
* It calls the parent class's doActivate method and then subscribes to the canvasInputListener's observeDbClick method.
|
|
@@ -85,14 +85,22 @@ export class XAxisScaleHandler extends ChartBaseElement {
|
|
|
85
85
|
this.setDblClickCallback = (cb) => (this.dblClickCallback = cb);
|
|
86
86
|
this.dblClickCallback = () => chartModel.doBasicScale();
|
|
87
87
|
this.dblTapCallback = () => chartModel.doBasicScale();
|
|
88
|
-
|
|
88
|
+
//#region drag-n-drop logic
|
|
89
|
+
this.dragNDropXComponent = new DragNDropXComponent(hitTest, {
|
|
89
90
|
onDragStart: this.onXDragStart,
|
|
90
91
|
onDragTick: this.onXDragTick,
|
|
91
92
|
onDragEnd: this.onXDragEnd,
|
|
92
93
|
}, this.canvasInputListener, this.chartPanComponent, {
|
|
93
94
|
dragPredicate: () => chartPanComponent.chartAreaPanHandler.chartPanningOptions.horizontal,
|
|
94
95
|
});
|
|
95
|
-
this.addChildEntity(dragNDropXComponent);
|
|
96
|
+
this.addChildEntity(this.dragNDropXComponent);
|
|
97
|
+
//#endregion
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Throttles chart-area horizontal drag to one animation frame when needed (percent Y-axis).
|
|
101
|
+
*/
|
|
102
|
+
setChartAreaXDragThrottled(shouldThrottle) {
|
|
103
|
+
this.dragNDropXComponent.setShouldThrottle(shouldThrottle);
|
|
96
104
|
}
|
|
97
105
|
/**
|
|
98
106
|
* This method is used to activate the canvas input listener and add a subscription to it.
|
|
@@ -23,6 +23,7 @@ import { XAxisLabelsModel, XAxisLabelsProvider } from './x-axis-labels.model';
|
|
|
23
23
|
import { XAxisScaleHandler } from './x-axis-scale.handler';
|
|
24
24
|
import { XAxisTimeLabelsDrawer } from './x-axis-time-labels.drawer';
|
|
25
25
|
import { HitTestCanvasModel } from '../../model/hit-test-canvas.model';
|
|
26
|
+
import { YAxisComponent } from '../y_axis/y-axis.component';
|
|
26
27
|
/**
|
|
27
28
|
* X-axis component, contains all x-axis calculation and rendering logic.
|
|
28
29
|
*/
|
|
@@ -34,12 +35,13 @@ export declare class XAxisComponent extends ChartBaseElement {
|
|
|
34
35
|
private scale;
|
|
35
36
|
private chartResizeHandler;
|
|
36
37
|
private timeZoneModel;
|
|
38
|
+
private yAxis;
|
|
37
39
|
xAxisDrawer: XAxisTimeLabelsDrawer;
|
|
38
40
|
xAxisLabelsDrawer: XAxisLabelsDrawer;
|
|
39
41
|
xAxisLabelsGenerator: XAxisLabelsGenerator;
|
|
40
42
|
readonly xAxisLabelsModel: XAxisLabelsModel;
|
|
41
43
|
xAxisScaleHandler: XAxisScaleHandler;
|
|
42
|
-
constructor(eventBus: EventBus, config: FullChartConfig, canvasModel: CanvasModel, chartComponent: ChartComponent, scale: ScaleModel, canvasBoundsContainer: CanvasBoundsContainer, canvasInputListener: CanvasInputListenerComponent, chartResizeHandler: ChartResizeHandler, drawingManager: DrawingManager, timeZoneModel: TimeZoneModel, chartPanComponent: ChartPanComponent, cursorHandler: CursorHandler, hitTestCanvasModel: HitTestCanvasModel);
|
|
44
|
+
constructor(eventBus: EventBus, config: FullChartConfig, canvasModel: CanvasModel, chartComponent: ChartComponent, scale: ScaleModel, canvasBoundsContainer: CanvasBoundsContainer, canvasInputListener: CanvasInputListenerComponent, chartResizeHandler: ChartResizeHandler, drawingManager: DrawingManager, timeZoneModel: TimeZoneModel, chartPanComponent: ChartPanComponent, cursorHandler: CursorHandler, hitTestCanvasModel: HitTestCanvasModel, yAxis: YAxisComponent);
|
|
43
45
|
/**
|
|
44
46
|
* This method is used to activate the chart and update the labels if there is a new data set or equivolume type.
|
|
45
47
|
* It subscribes to the chart type change, candles set subject, candles updated subject, and time zone change to generate new labels.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
*/
|
|
6
6
|
import { merge, animationFrameScheduler } from 'rxjs';
|
|
7
|
-
import { distinctUntilChanged, map, throttleTime, filter } from 'rxjs/operators';
|
|
7
|
+
import { distinctUntilChanged, map, throttleTime, filter, startWith } from 'rxjs/operators';
|
|
8
8
|
import { CanvasElement } from '../../canvas/canvas-bounds-container';
|
|
9
9
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
10
10
|
import { CompositeDrawer } from '../../drawers/composite.drawer';
|
|
@@ -20,7 +20,7 @@ import { availableBarTypes } from '../../chart.config';
|
|
|
20
20
|
* X-axis component, contains all x-axis calculation and rendering logic.
|
|
21
21
|
*/
|
|
22
22
|
export class XAxisComponent extends ChartBaseElement {
|
|
23
|
-
constructor(eventBus, config, canvasModel, chartComponent, scale, canvasBoundsContainer, canvasInputListener, chartResizeHandler, drawingManager, timeZoneModel, chartPanComponent, cursorHandler, hitTestCanvasModel) {
|
|
23
|
+
constructor(eventBus, config, canvasModel, chartComponent, scale, canvasBoundsContainer, canvasInputListener, chartResizeHandler, drawingManager, timeZoneModel, chartPanComponent, cursorHandler, hitTestCanvasModel, yAxis) {
|
|
24
24
|
super();
|
|
25
25
|
this.eventBus = eventBus;
|
|
26
26
|
this.config = config;
|
|
@@ -29,6 +29,7 @@ export class XAxisComponent extends ChartBaseElement {
|
|
|
29
29
|
this.scale = scale;
|
|
30
30
|
this.chartResizeHandler = chartResizeHandler;
|
|
31
31
|
this.timeZoneModel = timeZoneModel;
|
|
32
|
+
this.yAxis = yAxis;
|
|
32
33
|
/* This function assigns a callback to be executed when a double-click event is detected.
|
|
33
34
|
* It accepts one parameter `cb`, which is a callback function.
|
|
34
35
|
* When a double-click event occurs, the specified callback function `cb` will be invoked.
|
|
@@ -91,6 +92,11 @@ export class XAxisComponent extends ChartBaseElement {
|
|
|
91
92
|
this.addRxSubscription(this.chartComponent.chartModel.candlesUpdatedSubject
|
|
92
93
|
.pipe(map(() => lastOf(this.chartComponent.chartModel.mainCandleSeries.visualPoints)), distinctUntilChanged((a, b) => { var _a, _b; return ((_a = a === null || a === void 0 ? void 0 : a.candle) === null || _a === void 0 ? void 0 : _a.id) === ((_b = b === null || b === void 0 ? void 0 : b.candle) === null || _b === void 0 ? void 0 : _b.id); }), filter(notEmpty))
|
|
93
94
|
.subscribe(x => { var _a, _b; return (_b = (_a = this.xAxisLabelsGenerator) === null || _a === void 0 ? void 0 : _a.updateLastLabel) === null || _b === void 0 ? void 0 : _b.call(_a, x); }));
|
|
95
|
+
this.addRxSubscription(this.yAxis.axisTypeSetSubject
|
|
96
|
+
.pipe(startWith(this.yAxis.getAxisType()), distinctUntilChanged(), map((axisType) => axisType === 'percent'))
|
|
97
|
+
.subscribe(shouldThrottle => {
|
|
98
|
+
this.xAxisScaleHandler.setChartAreaXDragThrottled(shouldThrottle);
|
|
99
|
+
}));
|
|
94
100
|
}
|
|
95
101
|
/**
|
|
96
102
|
* Returns the xAxisDrawer object.
|
|
@@ -66,7 +66,7 @@ export function drawLabel(ctx, yAxisDescriptionsCtx, backgroundCtx, bounds, pane
|
|
|
66
66
|
}
|
|
67
67
|
const lineY = (_e = visualLabel.lineY) !== null && _e !== void 0 ? _e : visualLabel.y;
|
|
68
68
|
const _drawLine = () => showLine &&
|
|
69
|
-
avoidAntialiasing(ctx, () => drawLine(ctx, lineXStart, lineY, lineXEnd, lineY, 1, visualLabel.lineDash));
|
|
69
|
+
avoidAntialiasing(ctx, () => { var _a; return drawLine(ctx, lineXStart, lineY, lineXEnd, lineY, 1, (_a = visualLabel.lineDash) !== null && _a !== void 0 ? _a : [], visualLabel.lineCap); });
|
|
70
70
|
const _drawLabel = () => drawLabel(ctx, bounds, replaceMinusSign(text), centralY, visualLabel, config, colors.yAxis, false);
|
|
71
71
|
const drawLineLabel = () => {
|
|
72
72
|
_drawLine();
|
|
@@ -166,9 +166,12 @@ export class FancyYAxisLabelsModel extends ChartBaseElement {
|
|
|
166
166
|
* @returns {LabelGroup} - A new LabelGroup object with updated label coordinates.
|
|
167
167
|
*/
|
|
168
168
|
updateLabelsCoordinates(labels, points) {
|
|
169
|
-
return Object.assign(Object.assign({}, labels), { labels: labels.labels.map((label, idx) =>
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
return Object.assign(Object.assign({}, labels), { labels: labels.labels.map((label, idx) => {
|
|
170
|
+
var _a;
|
|
171
|
+
return (Object.assign(Object.assign({}, label), {
|
|
172
|
+
// Keep connector Y at the price level when the Y-axis price label box was shifted to avoid overlap
|
|
173
|
+
lineY: (_a = label.lineY) !== null && _a !== void 0 ? _a : label.y, y: points[idx] }));
|
|
174
|
+
}) });
|
|
172
175
|
}
|
|
173
176
|
/**
|
|
174
177
|
* Returns an Observable that emits a void value whenever the labels position is recalculated.
|
|
@@ -3,13 +3,14 @@
|
|
|
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 { YAxisConfig, FullChartColors } from '../../chart.config';
|
|
6
|
+
import { YAxisConfig, FullChartColors, YAxisLabelAppearanceType, YAxisLabelMode } from '../../chart.config';
|
|
7
7
|
import { Bounds } from '../../model/bounds.model';
|
|
8
8
|
export interface YAxisLabelDrawProps {
|
|
9
9
|
ctx: CanvasRenderingContext2D;
|
|
10
10
|
bounds: Bounds;
|
|
11
11
|
text: string;
|
|
12
12
|
centralY: number;
|
|
13
|
+
lineY?: number;
|
|
13
14
|
config: YAxisLabelDrawConfig;
|
|
14
15
|
subGroupId?: number;
|
|
15
16
|
}
|
|
@@ -26,6 +27,12 @@ export interface YAxisLabelDrawConfig {
|
|
|
26
27
|
paddingStart?: number;
|
|
27
28
|
rounded?: boolean;
|
|
28
29
|
lineDash?: Array<number>;
|
|
30
|
+
/** When set (e.g. `round` with short dash gaps), strokes render as dotted segments. */
|
|
31
|
+
lineCap?: CanvasLineCap;
|
|
32
|
+
/** Overrides chart-wide `components.yAxis.labels.settings.drawings.mode` for this label (e.g. drawings). */
|
|
33
|
+
yAxisLabelMode?: YAxisLabelMode;
|
|
34
|
+
/** Overrides chart-wide `components.yAxis.labels.settings.drawings.type` for this label (e.g. drawings). */
|
|
35
|
+
yAxisLabelType?: YAxisLabelAppearanceType;
|
|
29
36
|
}
|
|
30
37
|
export declare const DEFAULT_PRICE_LABEL_PADDING = 4;
|
|
31
38
|
/**
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
9
9
|
* If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
10
10
|
*/
|
|
11
|
-
import { getFontFromConfig } from '../../chart.config';
|
|
11
|
+
import { getFontFromConfig, } from '../../chart.config';
|
|
12
12
|
import { drawPriceLabel, drawRoundedRect } from '../../utils/canvas/canvas-drawing-functions.utils';
|
|
13
13
|
import { calculateSymbolHeight, calculateTextWidth } from '../../utils/canvas/canvas-font-measure-tool.utils';
|
|
14
14
|
import { getLabelTextColorByBackgroundColor } from '../../utils/canvas/canvas-text-functions.utils';
|
|
@@ -130,6 +130,10 @@ export declare class HoverProducerComponent extends ChartBaseElement {
|
|
|
130
130
|
*/
|
|
131
131
|
fireLastCross(): void;
|
|
132
132
|
setLongTouchCrosshairSuppressed(value: boolean): void;
|
|
133
|
+
/**
|
|
134
|
+
* Resets the current crosshair/touch state back to the default mobile idle state.
|
|
135
|
+
*/
|
|
136
|
+
resetCrossTool(clearMobile?: boolean): void;
|
|
133
137
|
/**
|
|
134
138
|
* Registers a hover producer part with the given id.
|
|
135
139
|
*
|
|
@@ -134,7 +134,7 @@ export class HoverProducerComponent extends ChartBaseElement {
|
|
|
134
134
|
this.paneManager.chartPanComponent.setChartPanningOptions(false, false);
|
|
135
135
|
}));
|
|
136
136
|
this.addRxSubscription(this.canvasInputListener.observeTouchEndDocument().subscribe(event => {
|
|
137
|
-
var _a, _b;
|
|
137
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
138
138
|
const { clientX, clientY } = event.changedTouches[0];
|
|
139
139
|
const { fixed, temp } = this.crossEventProducer.crossToolTouchInfo;
|
|
140
140
|
const x = clientX - this.canvasBoundsContainer.canvasOnPageLocation.x;
|
|
@@ -142,28 +142,32 @@ export class HoverProducerComponent extends ChartBaseElement {
|
|
|
142
142
|
// common tap without moving, hide crosstool
|
|
143
143
|
if (this.crossEventProducer.crossToolTouchInfo.isCommonTap &&
|
|
144
144
|
!checkChartIsMoving(x, temp.x, y, temp.y)) {
|
|
145
|
-
this.
|
|
146
|
-
this.longTouchActivatedSubject.next(false);
|
|
147
|
-
this.crossEventProducer.fireCrossClose();
|
|
148
|
-
this.crossEventProducer.crossToolHover = null;
|
|
149
|
-
this.crossEventProducer.crossToolTouchInfo.isSet = false;
|
|
145
|
+
this.resetCrossTool();
|
|
150
146
|
return;
|
|
151
147
|
}
|
|
152
148
|
if (!this.crossEventProducer.crossToolTouchInfo.isSet) {
|
|
153
149
|
this.crossEventProducer.crossToolTouchInfo.isSet = true;
|
|
154
|
-
|
|
150
|
+
const crossToolHover = this.crossEventProducer.crossToolHover;
|
|
151
|
+
const anchorX = (_a = crossToolHover === null || crossToolHover === void 0 ? void 0 : crossToolHover.x) !== null && _a !== void 0 ? _a : x;
|
|
152
|
+
const anchorY = (_b = crossToolHover === null || crossToolHover === void 0 ? void 0 : crossToolHover.y) !== null && _b !== void 0 ? _b : y;
|
|
155
153
|
this.crossEventProducer.crossToolTouchInfo.temp = {
|
|
156
|
-
x:
|
|
157
|
-
y:
|
|
154
|
+
x: anchorX,
|
|
155
|
+
y: anchorY,
|
|
158
156
|
};
|
|
159
157
|
this.crossEventProducer.crossToolTouchInfo.fixed = {
|
|
160
|
-
x,
|
|
161
|
-
y,
|
|
158
|
+
x: anchorX,
|
|
159
|
+
y: anchorY,
|
|
162
160
|
};
|
|
163
|
-
this.
|
|
161
|
+
const paneId = (_e = (_c = crossToolHover === null || crossToolHover === void 0 ? void 0 : crossToolHover.paneId) !== null && _c !== void 0 ? _c : (_d = this.paneManager.getPaneIfHit({ x: anchorX, y: anchorY })) === null || _d === void 0 ? void 0 : _d.uuid) !== null && _e !== void 0 ? _e : '';
|
|
162
|
+
const hover = crossToolHover !== null && crossToolHover !== void 0 ? crossToolHover : this.hover;
|
|
163
|
+
if (!hover) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
this.crossEventProducer.crossToolHover = Object.assign(Object.assign({}, hover), { x: anchorX, y: anchorY, paneId });
|
|
167
|
+
this.crossEventProducer.crossSubject.next([anchorX, anchorY, paneId]);
|
|
164
168
|
}
|
|
165
169
|
else {
|
|
166
|
-
const pane = (
|
|
170
|
+
const pane = (_g = (_f = this.crossEventProducer.crossToolHover) === null || _f === void 0 ? void 0 : _f.paneId) !== null && _g !== void 0 ? _g : 'CHART';
|
|
167
171
|
const paneBounds = this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(pane));
|
|
168
172
|
const paneYStart = paneBounds.y + 5;
|
|
169
173
|
const paneYEnd = paneBounds.y + paneBounds.height - 5;
|
|
@@ -172,6 +176,13 @@ export class HoverProducerComponent extends ChartBaseElement {
|
|
|
172
176
|
const newX = fixed.x < 0 ? 0 : fixed.x > paneBounds.width ? paneBounds.width : (fixed.x += xDiff);
|
|
173
177
|
const newY = fixed.y < paneYStart ? paneYStart : fixed.y > paneYEnd ? paneYEnd : (fixed.y += yDiff);
|
|
174
178
|
this.crossEventProducer.crossToolTouchInfo.fixed = { x: newX, y: newY };
|
|
179
|
+
this.crossEventProducer.crossToolTouchInfo.temp = { x: newX, y: newY };
|
|
180
|
+
const hover = (_h = this.crossEventProducer.crossToolHover) !== null && _h !== void 0 ? _h : this.hover;
|
|
181
|
+
if (!hover) {
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
this.crossEventProducer.crossToolHover = Object.assign(Object.assign({}, hover), { x: newX, y: newY, paneId: pane });
|
|
185
|
+
this.crossEventProducer.crossSubject.next([newX, newY, pane]);
|
|
175
186
|
}
|
|
176
187
|
}));
|
|
177
188
|
//#endregion
|
|
@@ -236,9 +247,16 @@ export class HoverProducerComponent extends ChartBaseElement {
|
|
|
236
247
|
* @param {VisualCandle} candle - The VisualCandle object to create the hover from.
|
|
237
248
|
*/
|
|
238
249
|
updateHover(candle) {
|
|
250
|
+
var _a, _b;
|
|
239
251
|
const updatedHover = this.createHoverFromCandle(candle);
|
|
240
252
|
if (this.hover && updatedHover) {
|
|
241
|
-
const
|
|
253
|
+
const shouldKeepSetTouchCrosshair = isMobile() &&
|
|
254
|
+
this.longTouchActivatedSubject.getValue() &&
|
|
255
|
+
this.crossEventProducer.crossSubject.getValue() !== null;
|
|
256
|
+
const crossToolHover = this.crossEventProducer.crossToolHover;
|
|
257
|
+
const hoverX = shouldKeepSetTouchCrosshair ? ((_a = crossToolHover === null || crossToolHover === void 0 ? void 0 : crossToolHover.x) !== null && _a !== void 0 ? _a : this.hover.x) : this.hover.x;
|
|
258
|
+
const hoverY = shouldKeepSetTouchCrosshair ? ((_b = crossToolHover === null || crossToolHover === void 0 ? void 0 : crossToolHover.y) !== null && _b !== void 0 ? _b : this.hover.y) : this.hover.y;
|
|
259
|
+
const hover = Object.assign(Object.assign({}, updatedHover), { x: hoverX, y: hoverY });
|
|
242
260
|
this.fireHover(hover);
|
|
243
261
|
}
|
|
244
262
|
}
|
|
@@ -293,6 +311,21 @@ export class HoverProducerComponent extends ChartBaseElement {
|
|
|
293
311
|
setLongTouchCrosshairSuppressed(value) {
|
|
294
312
|
this.longTouchCrosshairSuppressed = value;
|
|
295
313
|
}
|
|
314
|
+
/**
|
|
315
|
+
* Resets the current crosshair/touch state back to the default mobile idle state.
|
|
316
|
+
*/
|
|
317
|
+
resetCrossTool(clearMobile = false) {
|
|
318
|
+
this.paneManager.chartPanComponent.setChartPanningOptions(true, true);
|
|
319
|
+
this.longTouchActivatedSubject.next(false);
|
|
320
|
+
this.crossEventProducer.fireCrossClose();
|
|
321
|
+
this.crossEventProducer.crossToolHover = null;
|
|
322
|
+
this.crossEventProducer.crossToolTouchInfo.isSet = false;
|
|
323
|
+
if (clearMobile) {
|
|
324
|
+
this.crossEventProducer.crossToolTouchInfo.isCommonTap = false;
|
|
325
|
+
this.crossEventProducer.crossToolTouchInfo.fixed = { x: 0, y: 0 };
|
|
326
|
+
this.crossEventProducer.crossToolTouchInfo.temp = { x: 0, y: 0 };
|
|
327
|
+
}
|
|
328
|
+
}
|
|
296
329
|
/**
|
|
297
330
|
* Registers a hover producer part with the given id.
|
|
298
331
|
*
|
|
@@ -7,7 +7,7 @@ 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 { Price, Unit, ViewportModel, ViewportModelState, Zoom } from './scaling/viewport.model';
|
|
10
|
+
import { Price, Unit, ViewportModel, ViewportModelState, XScale, YScale, Zoom } from './scaling/viewport.model';
|
|
11
11
|
import { BoundsProvider } from './bounds.model';
|
|
12
12
|
import VisualCandle from './visual-candle';
|
|
13
13
|
export interface HighLowWithIndex {
|
|
@@ -16,11 +16,7 @@ export interface HighLowWithIndex {
|
|
|
16
16
|
highIdx: number;
|
|
17
17
|
lowIdx: number;
|
|
18
18
|
}
|
|
19
|
-
export interface ScaleHistoryItem {
|
|
20
|
-
xStart: Unit;
|
|
21
|
-
xEnd: Unit;
|
|
22
|
-
yStart: Unit;
|
|
23
|
-
yEnd: Unit;
|
|
19
|
+
export interface ScaleHistoryItem extends XScale, YScale {
|
|
24
20
|
}
|
|
25
21
|
export declare const getDefaultHighLowWithIndex: () => HighLowWithIndex;
|
|
26
22
|
export type ViewportPercent = number;
|
|
@@ -57,6 +57,8 @@ export interface ViewportModelState {
|
|
|
57
57
|
zoomY: Zoom;
|
|
58
58
|
inverseY: boolean;
|
|
59
59
|
}
|
|
60
|
+
export type XScale = Pick<ViewportModelState, 'xStart' | 'xEnd'>;
|
|
61
|
+
export type YScale = Pick<ViewportModelState, 'yStart' | 'yEnd'>;
|
|
60
62
|
/**
|
|
61
63
|
* Abstract viewport model.
|
|
62
64
|
* Viewport has 4 coordinates: xStart, xEnd, yStart and yEnd - all stored in {@link Unit}.
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2026 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
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
|
+
*/
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2026 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
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
|
+
*/
|
|
6
|
+
import { isCanvasPointInLowerHoverStrip } from '../canvas-lower-hover-strip.utils';
|
|
7
|
+
const baseBounds = () => ({
|
|
8
|
+
x: 0,
|
|
9
|
+
y: 0,
|
|
10
|
+
pageX: 0,
|
|
11
|
+
pageY: 0,
|
|
12
|
+
width: 1000,
|
|
13
|
+
height: 1000,
|
|
14
|
+
});
|
|
15
|
+
describe('canvas-lower-hover-strip.utils', () => {
|
|
16
|
+
it('returns true for a point in the lower strip (bottom offset 0)', () => {
|
|
17
|
+
const b = baseBounds();
|
|
18
|
+
expect(isCanvasPointInLowerHoverStrip({ x: 500, y: 900 }, b, 0)).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
it('returns false for a point in the upper area', () => {
|
|
21
|
+
const b = baseBounds();
|
|
22
|
+
expect(isCanvasPointInLowerHoverStrip({ x: 500, y: 100 }, b, 0)).toBe(false);
|
|
23
|
+
});
|
|
24
|
+
it('shifts the strip when bottomOffsetPx is non-zero', () => {
|
|
25
|
+
const b = baseBounds();
|
|
26
|
+
const yAtStripStartNoOffset = b.height * 0.85 + 10;
|
|
27
|
+
expect(isCanvasPointInLowerHoverStrip({ x: 1, y: yAtStripStartNoOffset - 1 }, b, 0)).toBe(false);
|
|
28
|
+
expect(isCanvasPointInLowerHoverStrip({ x: 1, y: yAtStripStartNoOffset }, b, 0)).toBe(true);
|
|
29
|
+
const bottomOffset = 50;
|
|
30
|
+
const yAtStripStartWithOffset = b.height * 0.85 - bottomOffset + 10;
|
|
31
|
+
expect(isCanvasPointInLowerHoverStrip({ x: 1, y: yAtStripStartWithOffset - 1 }, b, bottomOffset)).toBe(false);
|
|
32
|
+
expect(isCanvasPointInLowerHoverStrip({ x: 1, y: yAtStripStartWithOffset }, b, bottomOffset)).toBe(true);
|
|
33
|
+
});
|
|
34
|
+
});
|
|
@@ -46,7 +46,7 @@ export declare function drawPriceLabel(ctx: CanvasRenderingContext2D, x0: number
|
|
|
46
46
|
*
|
|
47
47
|
* @returns {void}
|
|
48
48
|
*/
|
|
49
|
-
export declare function drawLine(ctx: CanvasRenderingContext2D, x0: number, y0: number, x1: number, y1: number, thickness?: number, lineDash?: Array<number
|
|
49
|
+
export declare function drawLine(ctx: CanvasRenderingContext2D, x0: number, y0: number, x1: number, y1: number, thickness?: number, lineDash?: Array<number>, lineCap?: CanvasLineCap): void;
|
|
50
50
|
/**
|
|
51
51
|
* Try to avoid anti-aliasing
|
|
52
52
|
*/
|
|
@@ -109,10 +109,13 @@ export function drawPriceLabel(ctx, x0, y0, x1, y1, x2, y2, _width, rounded, ali
|
|
|
109
109
|
*
|
|
110
110
|
* @returns {void}
|
|
111
111
|
*/
|
|
112
|
-
export function drawLine(ctx, x0, y0, x1, y1, thickness = 1, lineDash = []) {
|
|
112
|
+
export function drawLine(ctx, x0, y0, x1, y1, thickness = 1, lineDash = [], lineCap) {
|
|
113
113
|
ctx.save();
|
|
114
114
|
ctx.setLineDash(lineDash);
|
|
115
115
|
ctx.lineWidth = thickness;
|
|
116
|
+
if (lineCap !== undefined) {
|
|
117
|
+
ctx.lineCap = lineCap;
|
|
118
|
+
}
|
|
116
119
|
ctx.beginPath();
|
|
117
120
|
ctx.moveTo(x0, y0);
|
|
118
121
|
ctx.lineTo(x1, y1);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2026 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
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
|
+
*/
|
|
6
|
+
import { Bounds } from '../model/bounds.model';
|
|
7
|
+
export interface CanvasPointerPoint {
|
|
8
|
+
readonly x: number;
|
|
9
|
+
readonly y: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Canvas-space hit test for the lower band (time scale / volume strip).
|
|
13
|
+
* Reusable for any UI that should react when the pointer is near the bottom of the chart.
|
|
14
|
+
*
|
|
15
|
+
* Rectangle matches the Figma hover region (full width, lower ~15% of canvas height plus offsets).
|
|
16
|
+
*/
|
|
17
|
+
export declare function isCanvasPointInLowerHoverStrip(point: CanvasPointerPoint, canvasBounds: Bounds, bottomOffsetPx: number): boolean;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2019 - 2026 Devexperts Solutions IE Limited
|
|
3
|
+
* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
|
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
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Canvas-space hit test for the lower band (time scale / volume strip).
|
|
8
|
+
* Reusable for any UI that should react when the pointer is near the bottom of the chart.
|
|
9
|
+
*
|
|
10
|
+
* Rectangle matches the Figma hover region (full width, lower ~15% of canvas height plus offsets).
|
|
11
|
+
*/
|
|
12
|
+
export function isCanvasPointInLowerHoverStrip(point, canvasBounds, bottomOffsetPx) {
|
|
13
|
+
const rectX = 0;
|
|
14
|
+
const rectY = canvasBounds.height * 0.85 - bottomOffsetPx + 10;
|
|
15
|
+
const rectWidth = canvasBounds.width;
|
|
16
|
+
const rectHeight = canvasBounds.height * 0.15 + bottomOffsetPx + 10;
|
|
17
|
+
const dx = point.x - rectX;
|
|
18
|
+
const dy = point.y - rectY;
|
|
19
|
+
return dx >= 0 && dx < rectWidth && dy >= 0 && dy < rectHeight;
|
|
20
|
+
}
|