@devexperts/dxcharts-lite 2.6.0 → 2.6.1
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/canvas/canvas-bounds-container.d.ts +1 -0
- package/dist/chart/canvas/canvas-bounds-container.js +4 -1
- package/dist/chart/chart.config.d.ts +8 -0
- package/dist/chart/chart.config.js +2 -1
- package/dist/chart/components/cross_tool/cross-tool.component.js +2 -2
- package/dist/chart/components/cross_tool/cross-tool.drawer.d.ts +3 -1
- package/dist/chart/components/cross_tool/cross-tool.drawer.js +4 -3
- package/dist/chart/components/cross_tool/cross-tool.model.d.ts +6 -6
- package/dist/chart/components/cross_tool/cross-tool.model.js +42 -11
- package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.js +3 -3
- package/dist/chart/components/high_low/high-low.drawer.js +1 -1
- package/dist/chart/components/pane/pane-manager.component.d.ts +5 -0
- package/dist/chart/components/pane/pane-manager.component.js +20 -0
- package/dist/chart/components/pane/pane.component.d.ts +9 -1
- package/dist/chart/components/pane/pane.component.js +16 -0
- package/dist/chart/components/x_axis/x-axis-draw.functions.js +2 -2
- package/dist/chart/components/x_axis/x-axis-scale.handler.d.ts +1 -0
- package/dist/chart/components/x_axis/x-axis-scale.handler.js +37 -8
- package/dist/chart/components/x_axis/x-axis-time-labels.drawer.js +2 -2
- package/dist/chart/inputhandlers/cross-event-producer.component.d.ts +22 -0
- package/dist/chart/inputhandlers/cross-event-producer.component.js +11 -1
- package/dist/chart/inputhandlers/hover-producer.component.d.ts +5 -3
- package/dist/chart/inputhandlers/hover-producer.component.js +70 -16
- package/dist/chart/inputhandlers/main-canvas-touch.handler.d.ts +10 -0
- package/dist/chart/inputhandlers/main-canvas-touch.handler.js +18 -0
- package/dist/chart/inputlisteners/canvas-input-listener.component.js +2 -7
- package/dist/chart/model/candle-series.model.js +1 -1
- package/dist/dxchart.min.js +4 -4
- package/package.json +1 -1
package/dist/chart/bootstrap.js
CHANGED
|
@@ -182,7 +182,7 @@ export default class ChartBootstrap {
|
|
|
182
182
|
// grid component
|
|
183
183
|
const verticalGridComponent = new GridComponent(mainCanvasModel, scaleModel, config, this.yAxisComponent.state, 'GRID', drawingManager, () => this.canvasBoundsContainer.getBounds(CanvasElement.ALL_PANES), () => this.canvasBoundsContainer.getBounds(chartPaneId), () => this.xAxisComponent.xAxisLabelsGenerator.labels, () => [], undefined, () => config.components.grid.visible);
|
|
184
184
|
this.chartComponents.push(verticalGridComponent);
|
|
185
|
-
this.hoverProducer = new HoverProducerComponent(this.crossEventProducer, scaleModel, config, chartModel, canvasInputListener, this.canvasBoundsContainer, this.paneManager, timeZoneModel, formatterFactory);
|
|
185
|
+
this.hoverProducer = new HoverProducerComponent(this.crossEventProducer, scaleModel, config, chartModel, canvasInputListener, this.canvasBoundsContainer, this.paneManager, timeZoneModel, chartPanComponent.mainCanvasTouchHandler, formatterFactory);
|
|
186
186
|
this.chartComponents.push(this.hoverProducer);
|
|
187
187
|
this.crossToolComponent = new CrossToolComponent(config, crossToolCanvasModel, canvasBoundsContainer, drawingManager, paneManager, this.crossEventProducer, this.hoverProducer);
|
|
188
188
|
this.chartComponents.push(this.crossToolComponent);
|
|
@@ -45,6 +45,7 @@ export declare class CanvasElement {
|
|
|
45
45
|
}
|
|
46
46
|
export declare const DEFAULT_BOUNDS: Bounds;
|
|
47
47
|
export declare const DEFAULT_MIN_PANE_HEIGHT = 20;
|
|
48
|
+
export declare const X_AXIS_MOBILE_PADDING: number;
|
|
48
49
|
/**
|
|
49
50
|
* This component listens EVENT_DRAW and recalculates bounds of canvas chart elements.
|
|
50
51
|
* {@link getBounds} method will always give actual placement of element you want.
|
|
@@ -45,6 +45,8 @@ const N_MAP_H = 35;
|
|
|
45
45
|
const N_MAP_BUTTON_W = 15;
|
|
46
46
|
const KNOTS_W_MOBILE_MULTIPLIER = 1.5;
|
|
47
47
|
const N_MAP_KNOT_W = isMobile() ? 8 * KNOTS_W_MOBILE_MULTIPLIER : 8;
|
|
48
|
+
// additional x axis height padding for mobiles, used for better usability on mobile devices
|
|
49
|
+
export const X_AXIS_MOBILE_PADDING = isMobile() ? 5 : 0;
|
|
48
50
|
/**
|
|
49
51
|
* we need to check that: heightRatios - 1 < 0.000001 after calculations between decimals
|
|
50
52
|
*/
|
|
@@ -390,7 +392,8 @@ export class CanvasBoundsContainer {
|
|
|
390
392
|
this.xAxisHeight =
|
|
391
393
|
fontHeight +
|
|
392
394
|
((_a = this.config.components.xAxis.padding.top) !== null && _a !== void 0 ? _a : 0) +
|
|
393
|
-
((_b = this.config.components.xAxis.padding.bottom) !== null && _b !== void 0 ? _b : 0)
|
|
395
|
+
((_b = this.config.components.xAxis.padding.bottom) !== null && _b !== void 0 ? _b : 0) +
|
|
396
|
+
X_AXIS_MOBILE_PADDING;
|
|
394
397
|
}
|
|
395
398
|
return this.xAxisHeight;
|
|
396
399
|
}
|
|
@@ -322,6 +322,10 @@ export interface ChartConfigComponentsChart {
|
|
|
322
322
|
selectedWidth: number;
|
|
323
323
|
minCandlesOffset: number;
|
|
324
324
|
histogram: ChartConfigComponentsHistogram;
|
|
325
|
+
/**
|
|
326
|
+
* The maximum amount of Y axis scales on a single chart
|
|
327
|
+
*/
|
|
328
|
+
maxYAxisScalesAmount: number;
|
|
325
329
|
sortCandles?: (candles: Candle[]) => Candle[];
|
|
326
330
|
}
|
|
327
331
|
export interface ChartConfigComponentsEvents {
|
|
@@ -482,6 +486,10 @@ export interface ChartConfigComponentsHighLow {
|
|
|
482
486
|
* Font config of high/low labels.
|
|
483
487
|
*/
|
|
484
488
|
font: string;
|
|
489
|
+
prefix: {
|
|
490
|
+
high: string;
|
|
491
|
+
low: string;
|
|
492
|
+
};
|
|
485
493
|
}
|
|
486
494
|
export interface ChartConfigComponentsCrossTool {
|
|
487
495
|
/**
|
|
@@ -71,6 +71,7 @@ export const getDefaultConfig = () => ({
|
|
|
71
71
|
histogram: {
|
|
72
72
|
barCapSize: 1,
|
|
73
73
|
},
|
|
74
|
+
maxYAxisScalesAmount: 10,
|
|
74
75
|
sortCandles: defaultSortCandles,
|
|
75
76
|
},
|
|
76
77
|
yAxis: {
|
|
@@ -192,7 +193,7 @@ export const getDefaultConfig = () => ({
|
|
|
192
193
|
logoWidth: 20,
|
|
193
194
|
logoHeight: 20,
|
|
194
195
|
},
|
|
195
|
-
highLow: { visible: false, font: '12px sans-serif' },
|
|
196
|
+
highLow: { visible: false, font: '12px sans-serif', prefix: { high: 'H: ', low: 'L: ' } },
|
|
196
197
|
highlights: {
|
|
197
198
|
visible: false,
|
|
198
199
|
fontFamily: 'Open Sans',
|
|
@@ -22,11 +22,11 @@ export class CrossToolComponent extends ChartBaseElement {
|
|
|
22
22
|
this.drawingManager = drawingManager;
|
|
23
23
|
this.paneManager = paneManager;
|
|
24
24
|
this.crossToolTypeDrawers = {};
|
|
25
|
-
this.model = new CrossToolModel(config.components.crossTool, this.crossToolCanvasModel, crossEventProducer, hoverProducer);
|
|
25
|
+
this.model = new CrossToolModel(config.components.crossTool, this.crossToolCanvasModel, crossEventProducer, hoverProducer, this.canvasBoundsContainer);
|
|
26
26
|
this.addChildEntity(this.model);
|
|
27
27
|
const clearCanvasDrawer = new ClearCanvasDrawer(this.crossToolCanvasModel);
|
|
28
28
|
this.registerDefaultDrawerTypes();
|
|
29
|
-
const crossToolDrawer = new CrossToolDrawer(this.model, this.crossToolCanvasModel, this.crossToolTypeDrawers);
|
|
29
|
+
const crossToolDrawer = new CrossToolDrawer(this.model, this.config, this.crossToolCanvasModel, this.crossToolTypeDrawers);
|
|
30
30
|
const compositeDrawer = new CompositeDrawer();
|
|
31
31
|
compositeDrawer.addDrawer(clearCanvasDrawer, 'CLEAR_CANVAS');
|
|
32
32
|
compositeDrawer.addDrawer(crossToolDrawer, 'CROSS_TOOL_DRAWER');
|
|
@@ -6,14 +6,16 @@
|
|
|
6
6
|
import { CanvasModel } from '../../model/canvas.model';
|
|
7
7
|
import { Drawer } from '../../drawers/drawing-manager';
|
|
8
8
|
import { CrossToolHover, CrossToolModel, CrossToolType } from './cross-tool.model';
|
|
9
|
+
import { FullChartConfig } from '../../chart.config';
|
|
9
10
|
export interface CrossToolTypeDrawer {
|
|
10
11
|
draw: (ctx: CanvasRenderingContext2D, hover: CrossToolHover) => void;
|
|
11
12
|
}
|
|
12
13
|
export declare class CrossToolDrawer implements Drawer {
|
|
13
14
|
private model;
|
|
15
|
+
private config;
|
|
14
16
|
private crossToolCanvasModel;
|
|
15
17
|
private readonly crossToolTypeDrawers;
|
|
16
|
-
constructor(model: CrossToolModel, crossToolCanvasModel: CanvasModel, crossToolTypeDrawers: Record<CrossToolType, CrossToolTypeDrawer>);
|
|
18
|
+
constructor(model: CrossToolModel, config: FullChartConfig, crossToolCanvasModel: CanvasModel, crossToolTypeDrawers: Record<CrossToolType, CrossToolTypeDrawer>);
|
|
17
19
|
/**
|
|
18
20
|
* Draws the cross tool on the canvas.
|
|
19
21
|
* @function
|
|
@@ -4,8 +4,9 @@
|
|
|
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
|
export class CrossToolDrawer {
|
|
7
|
-
constructor(model, crossToolCanvasModel, crossToolTypeDrawers) {
|
|
7
|
+
constructor(model, config, crossToolCanvasModel, crossToolTypeDrawers) {
|
|
8
8
|
this.model = model;
|
|
9
|
+
this.config = config;
|
|
9
10
|
this.crossToolCanvasModel = crossToolCanvasModel;
|
|
10
11
|
this.crossToolTypeDrawers = crossToolTypeDrawers;
|
|
11
12
|
}
|
|
@@ -18,12 +19,12 @@ export class CrossToolDrawer {
|
|
|
18
19
|
* @returns {void}
|
|
19
20
|
*/
|
|
20
21
|
draw() {
|
|
21
|
-
const drawer = this.crossToolTypeDrawers[this.
|
|
22
|
+
const drawer = this.crossToolTypeDrawers[this.config.components.crossTool.type];
|
|
22
23
|
if (drawer) {
|
|
23
24
|
this.model.currentHover && drawer.draw(this.crossToolCanvasModel.ctx, this.model.currentHover);
|
|
24
25
|
}
|
|
25
26
|
else {
|
|
26
|
-
console.error(`No cross tool drawer type registered for drawer type ${this.
|
|
27
|
+
console.error(`No cross tool drawer type registered for drawer type ${this.config.components.crossTool.type}`);
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
30
|
/**
|
|
@@ -9,6 +9,7 @@ import { CrossEventProducerComponent } from '../../inputhandlers/cross-event-pro
|
|
|
9
9
|
import { Hover, HoverProducerComponent } from '../../inputhandlers/hover-producer.component';
|
|
10
10
|
import { CanvasModel } from '../../model/canvas.model';
|
|
11
11
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
12
|
+
import { CanvasBoundsContainer } from '../../canvas/canvas-bounds-container';
|
|
12
13
|
export type CrossToolType = 'cross-and-labels' | 'only-labels' | 'none' | string;
|
|
13
14
|
export interface CrossToolHover {
|
|
14
15
|
x: number;
|
|
@@ -21,11 +22,11 @@ export declare class CrossToolModel extends ChartBaseElement {
|
|
|
21
22
|
private crossToolCanvasModel;
|
|
22
23
|
private crossEventProducer;
|
|
23
24
|
private hoverProducer;
|
|
25
|
+
private canvasBoundsContainer;
|
|
24
26
|
currentHoverSubject: BehaviorSubject<CrossToolHover | null>;
|
|
25
27
|
get currentHover(): CrossToolHover | null;
|
|
26
28
|
set currentHover(value: CrossToolHover | null);
|
|
27
|
-
|
|
28
|
-
constructor(config: Required<ChartConfigComponentsCrossTool>, crossToolCanvasModel: CanvasModel, crossEventProducer: CrossEventProducerComponent, hoverProducer: HoverProducerComponent);
|
|
29
|
+
constructor(config: Required<ChartConfigComponentsCrossTool>, crossToolCanvasModel: CanvasModel, crossEventProducer: CrossEventProducerComponent, hoverProducer: HoverProducerComponent, canvasBoundsContainer: CanvasBoundsContainer);
|
|
29
30
|
/**
|
|
30
31
|
* Sets the type of the CrossTool object.
|
|
31
32
|
*
|
|
@@ -35,9 +36,7 @@ export declare class CrossToolModel extends ChartBaseElement {
|
|
|
35
36
|
setType(type: CrossToolType): void;
|
|
36
37
|
/**
|
|
37
38
|
* Method to activate the cross tool.
|
|
38
|
-
* It subscribes to the
|
|
39
|
-
* It also subscribes to the eventBus's hover and close hover events and updates the hover and fires the draw event accordingly.
|
|
40
|
-
* It also subscribes to the chartModel's candlesSetSubject and timeZoneModel's observeTimeZoneChanged events and recalculates the cross tool X formatter.
|
|
39
|
+
* It subscribes to the hoverProducer's hover event and updates the crosstool.
|
|
41
40
|
*/
|
|
42
41
|
protected doActivate(): void;
|
|
43
42
|
/**
|
|
@@ -59,5 +58,6 @@ export declare class CrossToolModel extends ChartBaseElement {
|
|
|
59
58
|
* @param {number} hover.candleHover.closestOHLCY - The y coordinate of the closest OHLC price of the candle.
|
|
60
59
|
* @returns {void}
|
|
61
60
|
*/
|
|
62
|
-
|
|
61
|
+
updateCrossTool(hover: Hover, magnetTarget?: import("./cross-tool.component").MagnetTarget): void;
|
|
62
|
+
private updateCrossToolMobile;
|
|
63
63
|
}
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { BehaviorSubject } from 'rxjs';
|
|
7
7
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
8
|
-
import { CHART_UUID } from '../../canvas/canvas-bounds-container';
|
|
8
|
+
import { CanvasElement, CHART_UUID } from '../../canvas/canvas-bounds-container';
|
|
9
|
+
import { isMobile } from '../../utils/device/browser.utils';
|
|
9
10
|
export class CrossToolModel extends ChartBaseElement {
|
|
10
11
|
get currentHover() {
|
|
11
12
|
return this.currentHoverSubject.getValue();
|
|
@@ -13,16 +14,15 @@ export class CrossToolModel extends ChartBaseElement {
|
|
|
13
14
|
set currentHover(value) {
|
|
14
15
|
this.currentHoverSubject.next(value);
|
|
15
16
|
}
|
|
16
|
-
constructor(config, crossToolCanvasModel, crossEventProducer, hoverProducer) {
|
|
17
|
+
constructor(config, crossToolCanvasModel, crossEventProducer, hoverProducer, canvasBoundsContainer) {
|
|
17
18
|
super();
|
|
18
19
|
this.config = config;
|
|
19
20
|
this.crossToolCanvasModel = crossToolCanvasModel;
|
|
20
21
|
this.crossEventProducer = crossEventProducer;
|
|
21
22
|
this.hoverProducer = hoverProducer;
|
|
23
|
+
this.canvasBoundsContainer = canvasBoundsContainer;
|
|
22
24
|
// the main hover object which will be presented on UI
|
|
23
25
|
this.currentHoverSubject = new BehaviorSubject(null);
|
|
24
|
-
this.type = 'cross-and-labels';
|
|
25
|
-
this.type = config.type;
|
|
26
26
|
}
|
|
27
27
|
/**
|
|
28
28
|
* Sets the type of the CrossTool object.
|
|
@@ -31,19 +31,17 @@ export class CrossToolModel extends ChartBaseElement {
|
|
|
31
31
|
* @returns {void}
|
|
32
32
|
*/
|
|
33
33
|
setType(type) {
|
|
34
|
-
this.type = type;
|
|
34
|
+
this.config.type = type;
|
|
35
35
|
}
|
|
36
36
|
/**
|
|
37
37
|
* Method to activate the cross tool.
|
|
38
|
-
* It subscribes to the
|
|
39
|
-
* It also subscribes to the eventBus's hover and close hover events and updates the hover and fires the draw event accordingly.
|
|
40
|
-
* It also subscribes to the chartModel's candlesSetSubject and timeZoneModel's observeTimeZoneChanged events and recalculates the cross tool X formatter.
|
|
38
|
+
* It subscribes to the hoverProducer's hover event and updates the crosstool.
|
|
41
39
|
*/
|
|
42
40
|
doActivate() {
|
|
43
41
|
super.doActivate();
|
|
44
42
|
this.addRxSubscription(this.hoverProducer.hoverSubject.subscribe(hover => {
|
|
45
43
|
if (this.crossEventProducer.crossSubject.getValue() !== null && hover !== null) {
|
|
46
|
-
this.
|
|
44
|
+
isMobile() ? this.updateCrossToolMobile(hover) : this.updateCrossTool(hover);
|
|
47
45
|
}
|
|
48
46
|
else {
|
|
49
47
|
this.currentHover = null;
|
|
@@ -56,7 +54,7 @@ export class CrossToolModel extends ChartBaseElement {
|
|
|
56
54
|
* @private
|
|
57
55
|
*/
|
|
58
56
|
fireDraw() {
|
|
59
|
-
if (this.type !== 'none') {
|
|
57
|
+
if (this.config.type !== 'none') {
|
|
60
58
|
this.crossToolCanvasModel.fireDraw();
|
|
61
59
|
}
|
|
62
60
|
}
|
|
@@ -74,7 +72,7 @@ export class CrossToolModel extends ChartBaseElement {
|
|
|
74
72
|
* @param {number} hover.candleHover.closestOHLCY - The y coordinate of the closest OHLC price of the candle.
|
|
75
73
|
* @returns {void}
|
|
76
74
|
*/
|
|
77
|
-
|
|
75
|
+
updateCrossTool(hover, magnetTarget = this.config.magnetTarget) {
|
|
78
76
|
if (this.currentHover === null) {
|
|
79
77
|
this.currentHover = { x: hover.x, y: 0, time: hover.timeFormatted, paneId: hover.paneId };
|
|
80
78
|
}
|
|
@@ -110,4 +108,37 @@ export class CrossToolModel extends ChartBaseElement {
|
|
|
110
108
|
this.currentHover.paneId = hover.paneId;
|
|
111
109
|
this.currentHoverSubject.next(this.currentHover);
|
|
112
110
|
}
|
|
111
|
+
updateCrossToolMobile(hover) {
|
|
112
|
+
var _a;
|
|
113
|
+
// mobile crosstool works only after long touch event
|
|
114
|
+
if (!this.hoverProducer.longTouchActivatedSubject.getValue()) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const { fixed, temp, isSet } = this.crossEventProducer.crossToolTouchInfo;
|
|
118
|
+
// long touch makes crosstool fixed and the further moving will place crosstool under the current hover coordinates (ordinary logic)
|
|
119
|
+
// if crosstool is already set (long touch end event happened) the moving of chart will move crosstool according to it's initial (fixed position)
|
|
120
|
+
if (!isSet) {
|
|
121
|
+
this.updateCrossTool(hover);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
// additional crosstool move logic
|
|
125
|
+
const paneBounds = this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID(hover.paneId));
|
|
126
|
+
const offset = 5;
|
|
127
|
+
// take a difference inbetween current hover and temporary crosstool coordinates
|
|
128
|
+
const xDiff = hover.x - temp.x;
|
|
129
|
+
const yDiff = hover.y - temp.y;
|
|
130
|
+
// apply the difference to the fixed coordinates
|
|
131
|
+
const rawX = fixed.x + xDiff;
|
|
132
|
+
const rawY = fixed.y + yDiff;
|
|
133
|
+
const paneYStart = paneBounds.y + offset;
|
|
134
|
+
const paneYEnd = paneBounds.y + paneBounds.height - offset;
|
|
135
|
+
// check for chart bounds and don't move crosstool outside of it
|
|
136
|
+
const x = rawX < offset ? offset : rawX > paneBounds.width - offset ? paneBounds.width - offset : rawX;
|
|
137
|
+
const y = rawY < paneYStart ? paneYStart : rawY > paneYEnd ? paneYEnd : rawY;
|
|
138
|
+
const crossToolHover = (_a = this.hoverProducer.createHover(x, y, hover.paneId)) !== null && _a !== void 0 ? _a : hover;
|
|
139
|
+
const updatedHover = Object.assign(Object.assign({}, crossToolHover), { x,
|
|
140
|
+
y });
|
|
141
|
+
this.crossEventProducer.crossToolHover = updatedHover;
|
|
142
|
+
this.updateCrossTool(updatedHover);
|
|
143
|
+
}
|
|
113
144
|
}
|
|
@@ -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 { CanvasElement } from '../../../canvas/canvas-bounds-container';
|
|
6
|
+
import { CanvasElement, X_AXIS_MOBILE_PADDING } from '../../../canvas/canvas-bounds-container';
|
|
7
7
|
import { avoidAntialiasing, drawRoundedRect } from '../../../utils/canvas/canvas-drawing-functions.utils';
|
|
8
8
|
import { priceLabelDrawersMap } from '../../y_axis/price_labels/price-label.drawer';
|
|
9
9
|
export class CrossAndLabelsDrawerType {
|
|
@@ -98,12 +98,12 @@ export class CrossAndLabelsDrawerType {
|
|
|
98
98
|
const boxWidth = width + xLabelPaddingLeft + xLabelPaddingRight;
|
|
99
99
|
const boxHeight = fontHeight + xLabelPaddingTop + xLabelPaddingBottom;
|
|
100
100
|
const xBoxPos = Math.max(x - boxWidth / 2, 0);
|
|
101
|
-
const yBoxPos = xAxis.y + xLabelMarginTop;
|
|
101
|
+
const yBoxPos = xAxis.y + xLabelMarginTop + X_AXIS_MOBILE_PADDING / 2;
|
|
102
102
|
drawRoundedRect(ctx, xBoxPos, yBoxPos, boxWidth, boxHeight);
|
|
103
103
|
// label
|
|
104
104
|
ctx.fillStyle = crossToolColors.labelTextColor;
|
|
105
105
|
const xTextPos = Math.max(x - width / 2, xLabelPaddingLeft);
|
|
106
|
-
const yTextPos = xAxis.y + xLabelMarginTop + fontHeight + xLabelPaddingTop - 1; // -1 for vertical adjustment
|
|
106
|
+
const yTextPos = xAxis.y + xLabelMarginTop + fontHeight + X_AXIS_MOBILE_PADDING / 2 + xLabelPaddingTop - 1; // -1 for vertical adjustment
|
|
107
107
|
ctx.fillText(labelText, xTextPos, yTextPos);
|
|
108
108
|
ctx.restore();
|
|
109
109
|
}
|
|
@@ -73,7 +73,7 @@ export class HighLowDrawer {
|
|
|
73
73
|
*/
|
|
74
74
|
getMarkerText(yValue, type) {
|
|
75
75
|
const formattedValue = this.chartModel.pane.regularFormatter(yValue);
|
|
76
|
-
const prefix = type === 'high' ?
|
|
76
|
+
const prefix = type === 'high' ? this.config.components.highLow.prefix.high : this.config.components.highLow.prefix.low;
|
|
77
77
|
return `${prefix} ${formattedValue}`;
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
@@ -24,6 +24,7 @@ import { PaneComponent } from './pane.component';
|
|
|
24
24
|
import { DataSeriesModel } from '../../model/data-series.model';
|
|
25
25
|
import { HitTestCanvasModel } from '../../model/hit-test-canvas.model';
|
|
26
26
|
import { ChartResizeHandler } from '../../inputhandlers/chart-resize.handler';
|
|
27
|
+
export type MoveDataSeriesToPaneDirection = 'above' | 'below';
|
|
27
28
|
export declare class PaneManager extends ChartBaseElement {
|
|
28
29
|
private chartBaseModel;
|
|
29
30
|
private dynamicObjectsCanvasModel;
|
|
@@ -107,6 +108,10 @@ export declare class PaneManager extends ChartBaseElement {
|
|
|
107
108
|
* Shows a pane, use if the pane is hidden
|
|
108
109
|
*/
|
|
109
110
|
showPane(paneUUID: string): void;
|
|
111
|
+
/**
|
|
112
|
+
* Move data series to a certain pane, or create a new one if no pane is found
|
|
113
|
+
*/
|
|
114
|
+
moveDataSeriesToPane(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, paneUUID?: string, extent?: YExtentComponent, direction?: MoveDataSeriesToPaneDirection): void;
|
|
110
115
|
/**
|
|
111
116
|
* Adds cursors to the chart elements based on the provided uuid and cursor type.
|
|
112
117
|
* @private
|
|
@@ -188,6 +188,26 @@ export class PaneManager extends ChartBaseElement {
|
|
|
188
188
|
this.canvasBoundsContainer.showPaneBounds(paneUUID);
|
|
189
189
|
this.recalculateState();
|
|
190
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Move data series to a certain pane, or create a new one if no pane is found
|
|
193
|
+
*/
|
|
194
|
+
moveDataSeriesToPane(dataSeries, initialPane, initialExtent, paneUUID, extent, direction) {
|
|
195
|
+
const pane = paneUUID && this.panes[paneUUID];
|
|
196
|
+
if (!pane) {
|
|
197
|
+
const order = direction && direction === 'above' ? 0 : this.panesOrder.length;
|
|
198
|
+
const newPane = this.createPane(undefined, { order });
|
|
199
|
+
newPane.moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, newPane.mainExtent);
|
|
200
|
+
initialPane.yExtentComponents.length === 0 && this.removePane(initialPane.uuid);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (extent) {
|
|
204
|
+
pane.moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, extent);
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
pane.moveDataSeriesToNewExtentComponent(dataSeries, initialPane, initialExtent);
|
|
208
|
+
}
|
|
209
|
+
initialPane.yExtentComponents.length === 0 && this.removePane(initialPane.uuid);
|
|
210
|
+
}
|
|
191
211
|
/**
|
|
192
212
|
* Adds cursors to the chart elements based on the provided uuid and cursor type.
|
|
193
213
|
* @private
|
|
@@ -7,7 +7,7 @@ import { Subject } from 'rxjs';
|
|
|
7
7
|
import { CanvasAnimation } from '../../animation/canvas-animation';
|
|
8
8
|
import { CanvasBoundsContainer, HitBoundsTest } from '../../canvas/canvas-bounds-container';
|
|
9
9
|
import { CursorHandler } from '../../canvas/cursor.handler';
|
|
10
|
-
import { FullChartConfig } from '../../chart.config';
|
|
10
|
+
import { FullChartConfig, YAxisAlign } from '../../chart.config';
|
|
11
11
|
import { DrawingManager } from '../../drawers/drawing-manager';
|
|
12
12
|
import EventBus from '../../events/event-bus';
|
|
13
13
|
import { CanvasInputListenerComponent } from '../../inputlisteners/canvas-input-listener.component';
|
|
@@ -84,6 +84,14 @@ export declare class PaneComponent extends ChartBaseElement {
|
|
|
84
84
|
private addCursors;
|
|
85
85
|
createExtentComponent(options?: AtLeastOne<YExtentCreationOptions>): YExtentComponent;
|
|
86
86
|
removeExtentComponent(extentComponent: YExtentComponent): void;
|
|
87
|
+
/**
|
|
88
|
+
* Create new pane extent and attach data series to it
|
|
89
|
+
*/
|
|
90
|
+
moveDataSeriesToNewExtentComponent(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, align?: YAxisAlign): void;
|
|
91
|
+
/**
|
|
92
|
+
* Attach data series to existing y axis extent
|
|
93
|
+
*/
|
|
94
|
+
moveDataSeriesToExistingExtentComponent(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, extentComponent: YExtentComponent): void;
|
|
87
95
|
/**
|
|
88
96
|
* This method updates the view by calling the doAutoScale method of the scaleModel and firing the Draw event using the eventBus.
|
|
89
97
|
* @private
|
|
@@ -149,6 +149,22 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
149
149
|
this.yExtentComponents.forEach((c, idx) => (c.idx = idx));
|
|
150
150
|
this.canvasBoundsContainer.updateYAxisWidths();
|
|
151
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Create new pane extent and attach data series to it
|
|
154
|
+
*/
|
|
155
|
+
moveDataSeriesToNewExtentComponent(dataSeries, initialPane, initialExtent, align = 'right') {
|
|
156
|
+
const extent = this.createExtentComponent();
|
|
157
|
+
extent.yAxis.setYAxisAlign(align);
|
|
158
|
+
dataSeries.forEach(series => series.moveToExtent(extent));
|
|
159
|
+
initialExtent.dataSeries.size === 0 && initialPane.removeExtentComponent(initialExtent);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Attach data series to existing y axis extent
|
|
163
|
+
*/
|
|
164
|
+
moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, extentComponent) {
|
|
165
|
+
dataSeries.forEach(series => series.moveToExtent(extentComponent));
|
|
166
|
+
initialExtent.dataSeries.size === 0 && initialPane.removeExtentComponent(initialExtent);
|
|
167
|
+
}
|
|
152
168
|
/**
|
|
153
169
|
* This method updates the view by calling the doAutoScale method of the scaleModel and firing the Draw event using the eventBus.
|
|
154
170
|
* @private
|
|
@@ -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 { CanvasElement } from '../../canvas/canvas-bounds-container';
|
|
6
|
+
import { CanvasElement, X_AXIS_MOBILE_PADDING } from '../../canvas/canvas-bounds-container';
|
|
7
7
|
const DEFAULT_X_LABEL_PADDING = { x: 4, y: 4 };
|
|
8
8
|
/**
|
|
9
9
|
* Draws the label on X axis.
|
|
@@ -50,7 +50,7 @@ export function drawXAxisLabel(ctx, canvasBoundsContainer, config, label) {
|
|
|
50
50
|
}
|
|
51
51
|
ctx.fillStyle = label.color;
|
|
52
52
|
const xTextPos = boxStart + DEFAULT_X_LABEL_PADDING.x;
|
|
53
|
-
const yTextPos = xAxisBounds.y + offsetTop + fontSize
|
|
53
|
+
const yTextPos = xAxisBounds.y + offsetTop + fontSize + X_AXIS_MOBILE_PADDING / 2;
|
|
54
54
|
ctx.fillText(label.text, xTextPos, yTextPos);
|
|
55
55
|
ctx.restore();
|
|
56
56
|
}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
7
7
|
import { CanvasElement } from '../../canvas/canvas-bounds-container';
|
|
8
8
|
import { DragNDropXComponent } from '../dran-n-drop_helper/drag-n-drop-x.component';
|
|
9
|
+
// if you drag full X width from left to right - you will have x3 zoom, and vice-versa
|
|
10
|
+
const FULL_X_WIDTH_ZOOM_FACTOR = 3;
|
|
9
11
|
/**
|
|
10
12
|
* Handles the mouse drag on X axis - to zoom the viewport horizontally.
|
|
11
13
|
* @doc-tags scaling,zoom,viewport
|
|
@@ -21,10 +23,12 @@ export class XAxisScaleHandler extends ChartBaseElement {
|
|
|
21
23
|
this.hitTest = hitTest;
|
|
22
24
|
this.hitTestCanvasModel = hitTestCanvasModel;
|
|
23
25
|
this.lastXStart = 0;
|
|
26
|
+
this.lastXEnd = 0;
|
|
24
27
|
this.lastXWidth = 0;
|
|
25
28
|
this.lastXPxWidth = 0;
|
|
26
29
|
this.onXDragStart = () => {
|
|
27
30
|
this.lastXStart = this.scale.xStart;
|
|
31
|
+
this.lastXEnd = this.scale.xEnd;
|
|
28
32
|
this.lastXWidth = this.scale.xEnd - this.scale.xStart;
|
|
29
33
|
const bounds = this.canvasBoundsContainer.getBounds(CanvasElement.X_AXIS);
|
|
30
34
|
this.lastXPxWidth = bounds.width - this.canvasInputListener.currentPoint.x;
|
|
@@ -32,16 +36,41 @@ export class XAxisScaleHandler extends ChartBaseElement {
|
|
|
32
36
|
this.hitTestCanvasModel.hitTestDrawersPredicateSubject.next(false);
|
|
33
37
|
};
|
|
34
38
|
this.onXDragTick = (dragInfo) => {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
let { delta: absoluteXDelta } = dragInfo;
|
|
40
|
+
// mouse click or single tap drag
|
|
41
|
+
if (!this.touches || this.touches.length === 1) {
|
|
42
|
+
const newPxWidth = this.lastXPxWidth - absoluteXDelta;
|
|
43
|
+
// cursor goes beyond x-axis - maximum scale is reached
|
|
44
|
+
if (newPxWidth < 0) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const xZoomMult = this.lastXPxWidth / newPxWidth;
|
|
48
|
+
const newWidth = this.lastXWidth * xZoomMult;
|
|
49
|
+
const newXStart = this.lastXStart + (this.lastXWidth - newWidth);
|
|
50
|
+
this.scale.setXScale(newXStart, this.scale.xEnd);
|
|
39
51
|
return;
|
|
40
52
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
this.
|
|
53
|
+
// if multitouch - take the first two touch events and apply delta the following way:
|
|
54
|
+
// the touch on the left keeps the initial delta because left => right gesture
|
|
55
|
+
// the touch on the right has the reversed delta because the gesture is right => left
|
|
56
|
+
if (this.touches.length > 1) {
|
|
57
|
+
const left = Math.min(this.touches[0].clientX, this.touches[1].clientX);
|
|
58
|
+
absoluteXDelta = left === this.touches[0].clientX ? absoluteXDelta : -absoluteXDelta;
|
|
59
|
+
let xZoomMult;
|
|
60
|
+
if (absoluteXDelta < 0) {
|
|
61
|
+
xZoomMult = 1 / (1 + (-absoluteXDelta / this.lastXPxWidth) * (FULL_X_WIDTH_ZOOM_FACTOR - 1));
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
xZoomMult = 1 + (absoluteXDelta / this.lastXPxWidth) * (FULL_X_WIDTH_ZOOM_FACTOR - 1);
|
|
65
|
+
}
|
|
66
|
+
const newXWidth = this.lastXWidth * xZoomMult;
|
|
67
|
+
const delta = (newXWidth - this.lastXWidth) / 2;
|
|
68
|
+
const newXStart = this.lastXStart - delta;
|
|
69
|
+
const newXEnd = this.lastXEnd + delta;
|
|
70
|
+
if (this.lastXStart !== newXStart || this.lastXEnd !== newXEnd) {
|
|
71
|
+
this.scale.setXScale(newXStart, newXEnd);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
45
74
|
};
|
|
46
75
|
this.onXDragEnd = () => {
|
|
47
76
|
// Continue redrawing hit test
|
|
@@ -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 { CanvasElement } from '../../canvas/canvas-bounds-container';
|
|
6
|
+
import { CanvasElement, X_AXIS_MOBILE_PADDING } from '../../canvas/canvas-bounds-container';
|
|
7
7
|
import { calculateTextWidth } from '../../utils/canvas/canvas-font-measure-tool.utils';
|
|
8
8
|
/**
|
|
9
9
|
* This Drawer draws regular time labels for X Axis.
|
|
@@ -38,7 +38,7 @@ export class XAxisTimeLabelsDrawer {
|
|
|
38
38
|
ctx.fillRect(bounds.x, bounds.y, bounds.width, bounds.height);
|
|
39
39
|
const color = this.config.colors.xAxis.labelTextColor;
|
|
40
40
|
const labels = this.labelsProvider();
|
|
41
|
-
this.drawLabels(ctx, labels, bounds, color, fontHeight, fontFamily, offsetTop);
|
|
41
|
+
this.drawLabels(ctx, labels, bounds, color, fontHeight, fontFamily, offsetTop + X_AXIS_MOBILE_PADDING / 2);
|
|
42
42
|
ctx.restore();
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -8,15 +8,36 @@ import { CanvasBoundsContainer, HitBoundsTest, HitBoundsTestOptionsPartial } fro
|
|
|
8
8
|
import { CanvasInputListenerComponent } from '../inputlisteners/canvas-input-listener.component';
|
|
9
9
|
import { ChartBaseElement } from '../model/chart-base-element';
|
|
10
10
|
import { Unsubscriber } from '../utils/function.utils';
|
|
11
|
+
import { Pixel } from '../model/scaling/viewport.model';
|
|
12
|
+
import { Hover } from './hover-producer.component';
|
|
11
13
|
/**
|
|
12
14
|
* [x, y, uuid - Unique identifier for the subscription]
|
|
13
15
|
*/
|
|
14
16
|
export type CrossEvent = [number, number, string];
|
|
17
|
+
interface CrossToolTouchInfo {
|
|
18
|
+
fixed: {
|
|
19
|
+
x: Pixel;
|
|
20
|
+
y: Pixel;
|
|
21
|
+
};
|
|
22
|
+
temp: {
|
|
23
|
+
x: Pixel;
|
|
24
|
+
y: Pixel;
|
|
25
|
+
};
|
|
26
|
+
isSet: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* additional flag to determine ordinary and long taps
|
|
29
|
+
* crosstool shouldn't be hidden after longtouch event even if coordinates are the same
|
|
30
|
+
* becomes true after touchStart and false after longTouchStart
|
|
31
|
+
*/
|
|
32
|
+
isCommonTap: boolean;
|
|
33
|
+
}
|
|
15
34
|
export declare class CrossEventProducerComponent extends ChartBaseElement {
|
|
16
35
|
private canvasInputListener;
|
|
17
36
|
private canvasBoundsContainer;
|
|
18
37
|
panesSubscriptions: Partial<Record<string, Subscription>>;
|
|
19
38
|
crossSubject: BehaviorSubject<CrossEvent | null>;
|
|
39
|
+
crossToolHover: Hover | null;
|
|
40
|
+
crossToolTouchInfo: CrossToolTouchInfo;
|
|
20
41
|
constructor(canvasInputListener: CanvasInputListenerComponent, canvasBoundsContainer: CanvasBoundsContainer);
|
|
21
42
|
protected doActivate(): void;
|
|
22
43
|
/**
|
|
@@ -45,3 +66,4 @@ export declare class CrossEventProducerComponent extends ChartBaseElement {
|
|
|
45
66
|
*/
|
|
46
67
|
subscribeMouseOverHT(uuid: string, hitTest: HitBoundsTest): Unsubscriber;
|
|
47
68
|
}
|
|
69
|
+
export {};
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { BehaviorSubject, combineLatest } from 'rxjs';
|
|
7
7
|
import { filter } from 'rxjs/operators';
|
|
8
8
|
import { ChartBaseElement } from '../model/chart-base-element';
|
|
9
|
+
import { isMobile } from '../utils/device/browser.utils';
|
|
9
10
|
export class CrossEventProducerComponent extends ChartBaseElement {
|
|
10
11
|
constructor(canvasInputListener, canvasBoundsContainer) {
|
|
11
12
|
super();
|
|
@@ -13,6 +14,14 @@ export class CrossEventProducerComponent extends ChartBaseElement {
|
|
|
13
14
|
this.canvasBoundsContainer = canvasBoundsContainer;
|
|
14
15
|
this.panesSubscriptions = {};
|
|
15
16
|
this.crossSubject = new BehaviorSubject(null);
|
|
17
|
+
// mobile specific crosstool hover and touch info
|
|
18
|
+
this.crossToolHover = null;
|
|
19
|
+
this.crossToolTouchInfo = {
|
|
20
|
+
fixed: { x: 0, y: 0 },
|
|
21
|
+
temp: { x: 0, y: 0 },
|
|
22
|
+
isSet: false,
|
|
23
|
+
isCommonTap: false,
|
|
24
|
+
};
|
|
16
25
|
}
|
|
17
26
|
doActivate() {
|
|
18
27
|
super.doActivate();
|
|
@@ -62,7 +71,8 @@ export class CrossEventProducerComponent extends ChartBaseElement {
|
|
|
62
71
|
this.crossSubject.next(cross);
|
|
63
72
|
closeHoverFired = false;
|
|
64
73
|
}
|
|
65
|
-
|
|
74
|
+
// crosstool should be hidden if hovering nonpane only on desktop
|
|
75
|
+
if (!enter && !isMobile()) {
|
|
66
76
|
this.crossSubject.next(null);
|
|
67
77
|
closeHoverFired = true;
|
|
68
78
|
}
|