@devexperts/dxcharts-lite 2.6.0 → 2.6.2
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 +5 -4
- package/dist/chart/canvas/canvas-bounds-container.js +8 -5
- package/dist/chart/chart.config.d.ts +48 -12
- package/dist/chart/chart.config.js +27 -6
- package/dist/chart/components/chart/chart-area-pan.handler.d.ts +3 -2
- package/dist/chart/components/chart/chart-area-pan.handler.js +5 -4
- 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/events/events-custom-icons.d.ts +33 -0
- package/dist/chart/components/events/events-custom-icons.js +52 -0
- package/dist/chart/components/events/events.drawer.d.ts +5 -30
- package/dist/chart/components/events/events.drawer.js +33 -69
- package/dist/chart/components/high_low/high-low.drawer.js +1 -1
- package/dist/chart/components/pane/pane-manager.component.d.ts +6 -0
- package/dist/chart/components/pane/pane-manager.component.js +24 -3
- package/dist/chart/components/pane/pane.component.d.ts +16 -5
- package/dist/chart/components/pane/pane.component.js +27 -4
- package/dist/chart/components/resizer/bar-resizer.component.d.ts +1 -0
- package/dist/chart/components/resizer/bar-resizer.component.js +1 -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/components/y_axis/price_labels/y-axis-labels.model.d.ts +3 -1
- package/dist/chart/components/y_axis/price_labels/y-axis-labels.model.js +4 -1
- package/dist/chart/components/y_axis/y-axis-scale.handler.d.ts +2 -0
- package/dist/chart/components/y_axis/y-axis-scale.handler.js +12 -0
- 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/chart/model/data-series.model.js +18 -0
- package/dist/dxchart.min.js +4 -4
- package/package.json +1 -1
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Bounds } from '../../model/bounds.model';
|
|
7
7
|
import { CanvasBoundsContainer } from '../../canvas/canvas-bounds-container';
|
|
8
|
-
import {
|
|
8
|
+
import { FullChartConfig, EventColors } from '../../chart.config';
|
|
9
9
|
import { CanvasModel } from '../../model/canvas.model';
|
|
10
10
|
import { Drawer } from '../../drawers/drawing-manager';
|
|
11
11
|
import { DateTimeFormatter } from '../../model/date-time.formatter';
|
|
12
12
|
import { ChartModel } from '../chart/chart.model';
|
|
13
|
-
import { EconomicEvent, EventsModel,
|
|
13
|
+
import { EconomicEvent, EventsModel, EventWithId } from './events.model';
|
|
14
14
|
export declare class EventsDrawer implements Drawer {
|
|
15
15
|
private canvasModel;
|
|
16
16
|
private chartModel;
|
|
@@ -20,22 +20,6 @@ export declare class EventsDrawer implements Drawer {
|
|
|
20
20
|
private formatterProvider;
|
|
21
21
|
private customIcons;
|
|
22
22
|
constructor(canvasModel: CanvasModel, chartModel: ChartModel, config: FullChartConfig, canvasBoundsContainer: CanvasBoundsContainer, model: EventsModel, formatterProvider: () => DateTimeFormatter);
|
|
23
|
-
/**
|
|
24
|
-
* Creates a custom icon for a given event type.
|
|
25
|
-
* @param {EventType} type - The type of the event.
|
|
26
|
-
* @param {CustomIcon} [icon] - The custom icon object containing the normal and hover images.
|
|
27
|
-
* @returns {void}
|
|
28
|
-
*/
|
|
29
|
-
createCustomIcon(type: EventType, icon?: CustomIcon): void;
|
|
30
|
-
/**
|
|
31
|
-
* Creates an icon image from a string containing SVG data.
|
|
32
|
-
* @param {string} iconString - The string containing SVG data.
|
|
33
|
-
* @returns {Object} An object containing an Image object and the height of the SVG element.
|
|
34
|
-
*/
|
|
35
|
-
createIconImage(iconString: string): {
|
|
36
|
-
img: HTMLImageElement;
|
|
37
|
-
svgHeight: number;
|
|
38
|
-
};
|
|
39
23
|
/**
|
|
40
24
|
* Draws events on the chart canvas if they are visible according to the configuration.
|
|
41
25
|
* The events are filtered by type and then iterated over to draw them on the chart.
|
|
@@ -44,25 +28,16 @@ export declare class EventsDrawer implements Drawer {
|
|
|
44
28
|
* @returns {void}
|
|
45
29
|
*/
|
|
46
30
|
draw(): void;
|
|
47
|
-
/**
|
|
48
|
-
* Draws a custom SVG event on a canvas context.
|
|
49
|
-
* @param {CanvasRenderingContext2D} ctx - The canvas context to draw on.
|
|
50
|
-
* @param {number} x - The x coordinate of the event.
|
|
51
|
-
* @param {Bounds} bounds - The bounds of the event.
|
|
52
|
-
* @param {EventWithId} event - The event to draw.
|
|
53
|
-
* @returns {void}
|
|
54
|
-
*/
|
|
55
|
-
drawCustomSvgEvent(ctx: CanvasRenderingContext2D, x: number, bounds: Bounds, event: EventWithId): void;
|
|
56
31
|
/**
|
|
57
32
|
* Draws a default event on a canvas context.
|
|
58
33
|
* @param {CanvasRenderingContext2D} ctx - The canvas context to draw on.
|
|
59
34
|
* @param {number} x - The x coordinate of the event.
|
|
60
35
|
* @param {Bounds} bounds - The bounds of the event.
|
|
61
36
|
* @param {EventWithId} event - The event to draw.
|
|
62
|
-
* @param {
|
|
37
|
+
* @param {EventColors} colors - The colors of the event.
|
|
63
38
|
* @returns {void}
|
|
64
39
|
*/
|
|
65
|
-
drawDefaultEvent(ctx: CanvasRenderingContext2D, x: number, bounds: Bounds, event: EventWithId,
|
|
40
|
+
drawDefaultEvent(ctx: CanvasRenderingContext2D, x: number, bounds: Bounds, event: EventWithId, colors: EventColors): void;
|
|
66
41
|
/**
|
|
67
42
|
* This function is responsible for drawing a label on the canvas at a given x coordinate. The label contains a formatted timestamp of a given event. The function takes two parameters: x, which is the x coordinate where the label will be drawn, and event, which is an object containing information about the event, including its timestamp and type.
|
|
68
43
|
* The function first gets the canvas context and the bounds of the x-axis. It then retrieves the font family, font height, and top padding from the configuration object. The y coordinate of the label is calculated based on the font height, top padding, and the y coordinate of the x-axis bounds. The font is set using the retrieved font family and font height.
|
|
@@ -81,6 +56,6 @@ export declare class EventsDrawer implements Drawer {
|
|
|
81
56
|
* Returns the size of an event based on its style
|
|
82
57
|
* @param {EconomicEvent} event - The event to get the size of
|
|
83
58
|
* @returns {number} - The size of the event
|
|
84
|
-
|
|
59
|
+
|
|
85
60
|
*/
|
|
86
61
|
export declare function getEventSize(event: EconomicEvent): number;
|
|
@@ -4,12 +4,18 @@
|
|
|
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 { CanvasElement } from '../../canvas/canvas-bounds-container';
|
|
7
|
+
import { createCustomIcon, drawCustomSvgIcon, getIconHash } from './events-custom-icons';
|
|
7
8
|
const eventsSizesDict = {
|
|
8
9
|
'rhombus-small': 4,
|
|
9
10
|
rhombus: 6,
|
|
10
11
|
'rhombus-large': 8,
|
|
11
12
|
};
|
|
12
|
-
const
|
|
13
|
+
const iconTypes = [
|
|
14
|
+
'earnings',
|
|
15
|
+
'dividends',
|
|
16
|
+
'splits',
|
|
17
|
+
'conference-calls',
|
|
18
|
+
];
|
|
13
19
|
export class EventsDrawer {
|
|
14
20
|
constructor(canvasModel, chartModel, config, canvasBoundsContainer, model, formatterProvider) {
|
|
15
21
|
this.canvasModel = canvasModel;
|
|
@@ -22,48 +28,14 @@ export class EventsDrawer {
|
|
|
22
28
|
this.customIcons = {};
|
|
23
29
|
const iconsConfig = this.config.components.events.icons;
|
|
24
30
|
if (iconsConfig) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
* Creates a custom icon for a given event type.
|
|
33
|
-
* @param {EventType} type - The type of the event.
|
|
34
|
-
* @param {CustomIcon} [icon] - The custom icon object containing the normal and hover images.
|
|
35
|
-
* @returns {void}
|
|
36
|
-
*/
|
|
37
|
-
createCustomIcon(type, icon) {
|
|
38
|
-
if (icon) {
|
|
39
|
-
const normal = this.createIconImage(icon.normal);
|
|
40
|
-
const hover = this.createIconImage(icon.hover);
|
|
41
|
-
this.customIcons[getIconHash(type, 'normal')] = normal;
|
|
42
|
-
this.customIcons[getIconHash(type, 'hover')] = hover;
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Creates an icon image from a string containing SVG data.
|
|
47
|
-
* @param {string} iconString - The string containing SVG data.
|
|
48
|
-
* @returns {Object} An object containing an Image object and the height of the SVG element.
|
|
49
|
-
*/
|
|
50
|
-
createIconImage(iconString) {
|
|
51
|
-
var _a;
|
|
52
|
-
const parser = new DOMParser();
|
|
53
|
-
const svgSelector = parser.parseFromString(iconString, 'text/html').querySelector('svg');
|
|
54
|
-
let svgHeight = 0;
|
|
55
|
-
if (svgSelector) {
|
|
56
|
-
svgHeight = parseInt((_a = svgSelector.getAttribute('height')) !== null && _a !== void 0 ? _a : '', 10);
|
|
31
|
+
iconTypes.forEach(type => {
|
|
32
|
+
const customIcon = createCustomIcon(type, iconsConfig[type]);
|
|
33
|
+
if (customIcon) {
|
|
34
|
+
this.customIcons[getIconHash(customIcon.type, 'normal')] = customIcon.normal;
|
|
35
|
+
this.customIcons[getIconHash(customIcon.type, 'hover')] = customIcon.hover;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
57
38
|
}
|
|
58
|
-
const svg64 = btoa(iconString);
|
|
59
|
-
const b64Start = 'data:image/svg+xml;base64,';
|
|
60
|
-
const image64 = b64Start + svg64;
|
|
61
|
-
const img = new Image();
|
|
62
|
-
img.src = image64;
|
|
63
|
-
return {
|
|
64
|
-
img,
|
|
65
|
-
svgHeight,
|
|
66
|
-
};
|
|
67
39
|
}
|
|
68
40
|
/**
|
|
69
41
|
* Draws events on the chart canvas if they are visible according to the configuration.
|
|
@@ -83,20 +55,28 @@ export class EventsDrawer {
|
|
|
83
55
|
this.model.events
|
|
84
56
|
.filter(e => this.config.components.events.eventsVisibility[e.type])
|
|
85
57
|
.forEach(event => {
|
|
58
|
+
var _a, _b, _c, _d;
|
|
86
59
|
const x = this.chartModel.candleFromTimestamp(event.timestamp).xCenter(this.chartModel.scale);
|
|
87
60
|
if (x > chartBounds.x && x < chartBounds.x + chartBounds.width) {
|
|
88
|
-
const
|
|
89
|
-
ctx.strokeStyle = color;
|
|
61
|
+
const colors = this.config.colors.events[event.type];
|
|
62
|
+
ctx.strokeStyle = (_b = (_a = colors.line) !== null && _a !== void 0 ? _a : colors.normal) !== null && _b !== void 0 ? _b : colors.color;
|
|
90
63
|
// check custom icon in cache
|
|
91
64
|
if (this.customIcons[getIconHash(event.type, 'hover')] !== undefined) {
|
|
92
|
-
|
|
65
|
+
const point = { x, y: bounds.y + bounds.height / 2 };
|
|
66
|
+
const isHovered = this.model.hoveredEvent.getValue() === event;
|
|
67
|
+
drawCustomSvgIcon(ctx, this.customIcons, point, event.type, isHovered);
|
|
93
68
|
}
|
|
94
69
|
else {
|
|
95
|
-
this.drawDefaultEvent(ctx, x, bounds, event,
|
|
70
|
+
this.drawDefaultEvent(ctx, x, bounds, event, colors);
|
|
96
71
|
}
|
|
97
72
|
// draw vertical line and label for the hovered event
|
|
98
73
|
if (this.model.hoveredEvent.getValue() === event) {
|
|
74
|
+
const line = this.config.components.events.line;
|
|
75
|
+
const width = line && line[event.type] && ((_c = line[event.type]) === null || _c === void 0 ? void 0 : _c.width);
|
|
76
|
+
const dash = line && line[event.type] && ((_d = line[event.type]) === null || _d === void 0 ? void 0 : _d.dash);
|
|
77
|
+
ctx.lineWidth = width !== null && width !== void 0 ? width : 1;
|
|
99
78
|
ctx.beginPath();
|
|
79
|
+
ctx.setLineDash(dash !== null && dash !== void 0 ? dash : []);
|
|
100
80
|
ctx.moveTo(x, chartBounds.y);
|
|
101
81
|
ctx.lineTo(x, bounds.y + bounds.height / 2);
|
|
102
82
|
ctx.stroke();
|
|
@@ -109,37 +89,19 @@ export class EventsDrawer {
|
|
|
109
89
|
});
|
|
110
90
|
ctx.restore();
|
|
111
91
|
}
|
|
112
|
-
/**
|
|
113
|
-
* Draws a custom SVG event on a canvas context.
|
|
114
|
-
* @param {CanvasRenderingContext2D} ctx - The canvas context to draw on.
|
|
115
|
-
* @param {number} x - The x coordinate of the event.
|
|
116
|
-
* @param {Bounds} bounds - The bounds of the event.
|
|
117
|
-
* @param {EventWithId} event - The event to draw.
|
|
118
|
-
* @returns {void}
|
|
119
|
-
*/
|
|
120
|
-
drawCustomSvgEvent(ctx, x, bounds, event) {
|
|
121
|
-
const y = bounds.y + bounds.height / 2;
|
|
122
|
-
const normal = this.customIcons[getIconHash(event.type, 'normal')];
|
|
123
|
-
const hover = this.customIcons[getIconHash(event.type, 'hover')];
|
|
124
|
-
if (this.model.hoveredEvent.getValue() === event) {
|
|
125
|
-
ctx.drawImage(hover.img, x - hover.svgHeight / 2, y - hover.svgHeight / 2);
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
ctx.drawImage(normal.img, x - normal.svgHeight / 2, y - normal.svgHeight / 2);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
92
|
/**
|
|
132
93
|
* Draws a default event on a canvas context.
|
|
133
94
|
* @param {CanvasRenderingContext2D} ctx - The canvas context to draw on.
|
|
134
95
|
* @param {number} x - The x coordinate of the event.
|
|
135
96
|
* @param {Bounds} bounds - The bounds of the event.
|
|
136
97
|
* @param {EventWithId} event - The event to draw.
|
|
137
|
-
* @param {
|
|
98
|
+
* @param {EventColors} colors - The colors of the event.
|
|
138
99
|
* @returns {void}
|
|
139
100
|
*/
|
|
140
|
-
drawDefaultEvent(ctx, x, bounds, event,
|
|
101
|
+
drawDefaultEvent(ctx, x, bounds, event, colors) {
|
|
102
|
+
var _a, _b, _c;
|
|
141
103
|
const y = bounds.y + bounds.height / 2;
|
|
142
|
-
ctx.fillStyle = color;
|
|
104
|
+
ctx.fillStyle = (_a = colors.normal) !== null && _a !== void 0 ? _a : colors.color;
|
|
143
105
|
// draw figure
|
|
144
106
|
ctx.lineWidth = 1.5; // 1.5 pixels
|
|
145
107
|
const size = getEventSize(event);
|
|
@@ -150,9 +112,11 @@ export class EventsDrawer {
|
|
|
150
112
|
ctx.lineTo(x, y + size);
|
|
151
113
|
ctx.closePath();
|
|
152
114
|
if (this.model.hoveredEvent.getValue() === event) {
|
|
115
|
+
ctx.fillStyle = (_b = colors.hover) !== null && _b !== void 0 ? _b : colors.color;
|
|
153
116
|
ctx.fill();
|
|
154
117
|
}
|
|
155
118
|
else {
|
|
119
|
+
ctx.strokeStyle = (_c = colors.normal) !== null && _c !== void 0 ? _c : colors.color;
|
|
156
120
|
ctx.stroke();
|
|
157
121
|
}
|
|
158
122
|
}
|
|
@@ -193,7 +157,7 @@ export class EventsDrawer {
|
|
|
193
157
|
* Returns the size of an event based on its style
|
|
194
158
|
* @param {EconomicEvent} event - The event to get the size of
|
|
195
159
|
* @returns {number} - The size of the event
|
|
196
|
-
|
|
160
|
+
|
|
197
161
|
*/
|
|
198
162
|
export function getEventSize(event) {
|
|
199
163
|
return eventsSizesDict[event.style];
|
|
@@ -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;
|
|
@@ -70,6 +71,7 @@ export declare class PaneManager extends ChartBaseElement {
|
|
|
70
71
|
/**
|
|
71
72
|
* Creates sub-plot on the chart with y-axis
|
|
72
73
|
* @param uuid
|
|
74
|
+
* @param {AtLeastOne<YExtentCreationOptions>} options
|
|
73
75
|
* @returns
|
|
74
76
|
*/
|
|
75
77
|
createPane(uuid?: string, options?: AtLeastOne<YExtentCreationOptions>): PaneComponent;
|
|
@@ -107,6 +109,10 @@ export declare class PaneManager extends ChartBaseElement {
|
|
|
107
109
|
* Shows a pane, use if the pane is hidden
|
|
108
110
|
*/
|
|
109
111
|
showPane(paneUUID: string): void;
|
|
112
|
+
/**
|
|
113
|
+
* Move data series to a certain pane, or create a new one if no pane is found
|
|
114
|
+
*/
|
|
115
|
+
moveDataSeriesToPane(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, paneUUID?: string, extent?: YExtentComponent, direction?: MoveDataSeriesToPaneDirection, index?: number): void;
|
|
110
116
|
/**
|
|
111
117
|
* Adds cursors to the chart elements based on the provided uuid and cursor type.
|
|
112
118
|
* @private
|
|
@@ -8,7 +8,7 @@ import { CHART_UUID, CanvasElement } from '../../canvas/canvas-bounds-container'
|
|
|
8
8
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
9
9
|
import { uuid as generateUuid } from '../../utils/uuid.utils';
|
|
10
10
|
import { createHighLowOffsetCalculator } from '../chart/data-series.high-low-provider';
|
|
11
|
-
import { BarResizerComponent } from '../resizer/bar-resizer.component';
|
|
11
|
+
import { BarResizerComponent, RESIZER_HIT_TEST_EXTENSION } from '../resizer/bar-resizer.component';
|
|
12
12
|
import { createDefaultYExtentHighLowProvider, } from './extent/y-extent-component';
|
|
13
13
|
import { PaneHitTestController } from './pane-hit-test.controller';
|
|
14
14
|
import { PaneComponent } from './pane.component';
|
|
@@ -63,7 +63,7 @@ export class PaneManager extends ChartBaseElement {
|
|
|
63
63
|
*/
|
|
64
64
|
addResizer(uuid) {
|
|
65
65
|
const resizerHT = this.canvasBoundsContainer.getBoundsHitTest(CanvasElement.PANE_UUID_RESIZER(uuid), {
|
|
66
|
-
extensionY: this.config.components.paneResizer.dragZone,
|
|
66
|
+
extensionY: this.config.components.paneResizer.dragZone + RESIZER_HIT_TEST_EXTENSION,
|
|
67
67
|
});
|
|
68
68
|
const dragPredicate = () => this.chartBaseModel.mainVisualPoints.length !== 0;
|
|
69
69
|
const dragTick = () => {
|
|
@@ -90,6 +90,7 @@ export class PaneManager extends ChartBaseElement {
|
|
|
90
90
|
/**
|
|
91
91
|
* Creates sub-plot on the chart with y-axis
|
|
92
92
|
* @param uuid
|
|
93
|
+
* @param {AtLeastOne<YExtentCreationOptions>} options
|
|
93
94
|
* @returns
|
|
94
95
|
*/
|
|
95
96
|
createPane(uuid = generateUuid(), options) {
|
|
@@ -188,6 +189,26 @@ export class PaneManager extends ChartBaseElement {
|
|
|
188
189
|
this.canvasBoundsContainer.showPaneBounds(paneUUID);
|
|
189
190
|
this.recalculateState();
|
|
190
191
|
}
|
|
192
|
+
/**
|
|
193
|
+
* Move data series to a certain pane, or create a new one if no pane is found
|
|
194
|
+
*/
|
|
195
|
+
moveDataSeriesToPane(dataSeries, initialPane, initialExtent, paneUUID, extent, direction, index = 0) {
|
|
196
|
+
const pane = paneUUID && this.panes[paneUUID];
|
|
197
|
+
if (!pane) {
|
|
198
|
+
const order = direction && direction === 'above' ? index : this.panesOrder.length + index;
|
|
199
|
+
const newPane = this.createPane(paneUUID, { order });
|
|
200
|
+
newPane.moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, newPane.mainExtent);
|
|
201
|
+
initialPane.yExtentComponents.length === 0 && this.removePane(initialPane.uuid);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (extent) {
|
|
205
|
+
pane.moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, extent);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
pane.moveDataSeriesToNewExtentComponent(dataSeries, initialPane, initialExtent, initialExtent.yAxis.state.align);
|
|
209
|
+
}
|
|
210
|
+
initialPane.yExtentComponents.length === 0 && this.removePane(initialPane.uuid);
|
|
211
|
+
}
|
|
191
212
|
/**
|
|
192
213
|
* Adds cursors to the chart elements based on the provided uuid and cursor type.
|
|
193
214
|
* @private
|
|
@@ -200,7 +221,7 @@ export class PaneManager extends ChartBaseElement {
|
|
|
200
221
|
const paneResizer = CanvasElement.PANE_UUID_RESIZER(uuid);
|
|
201
222
|
this.cursorHandler.setCursorForCanvasEl(pane, cursor);
|
|
202
223
|
this.config.components.paneResizer.visible &&
|
|
203
|
-
this.cursorHandler.setCursorForCanvasEl(paneResizer, this.config.components.paneResizer.cursor, this.config.components.paneResizer.dragZone);
|
|
224
|
+
this.cursorHandler.setCursorForCanvasEl(paneResizer, this.config.components.paneResizer.cursor, this.config.components.paneResizer.dragZone + RESIZER_HIT_TEST_EXTENSION);
|
|
204
225
|
return () => {
|
|
205
226
|
this.cursorHandler.removeCursorForCanvasEl(pane);
|
|
206
227
|
this.config.components.paneResizer.visible && this.cursorHandler.removeCursorForCanvasEl(paneResizer);
|
|
@@ -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';
|
|
@@ -51,6 +51,7 @@ export declare class PaneComponent extends ChartBaseElement {
|
|
|
51
51
|
*/
|
|
52
52
|
ht: HitBoundsTest;
|
|
53
53
|
yExtentComponents: YExtentComponent[];
|
|
54
|
+
yExtentComponentsChangedSubject: Subject<void>;
|
|
54
55
|
get scale(): ScaleModel;
|
|
55
56
|
get yAxis(): YAxisComponent;
|
|
56
57
|
get dataSeries(): DataSeriesModel<import("../../model/data-series.model").DataSeriesPoint, import("../../model/data-series.model").VisualSeriesPoint>[];
|
|
@@ -68,8 +69,10 @@ export declare class PaneComponent extends ChartBaseElement {
|
|
|
68
69
|
/**
|
|
69
70
|
* Creates a new GridComponent instance with the provided parameters.
|
|
70
71
|
* @param {string} uuid - The unique identifier of the pane.
|
|
71
|
-
* @param {ScaleModel}
|
|
72
|
-
* @param {
|
|
72
|
+
* @param {ScaleModel} scale - The scale model used to calculate the scale of the grid.
|
|
73
|
+
* @param {YAxisConfig} yAxisState - y Axis Config
|
|
74
|
+
* @param {() => NumericAxisLabel[]} yAxisLabelsGetter
|
|
75
|
+
* @param {() => Unit} yAxisBaselineGetter
|
|
73
76
|
* @returns {GridComponent} - The newly created GridComponent instance.
|
|
74
77
|
*/
|
|
75
78
|
private createGridComponent;
|
|
@@ -77,13 +80,21 @@ export declare class PaneComponent extends ChartBaseElement {
|
|
|
77
80
|
* Creates a handler for Y-axis panning of the chart.
|
|
78
81
|
* @private
|
|
79
82
|
* @param {string} uuid - The unique identifier of the chart pane.
|
|
80
|
-
* @param {ScaleModel}
|
|
81
|
-
* @returns
|
|
83
|
+
* @param {ScaleModel} scale - The scale model of the chart.
|
|
84
|
+
* @returns [Unsubscriber, DragNDropYComponent]
|
|
82
85
|
*/
|
|
83
86
|
private createYPanHandler;
|
|
84
87
|
private addCursors;
|
|
85
88
|
createExtentComponent(options?: AtLeastOne<YExtentCreationOptions>): YExtentComponent;
|
|
86
89
|
removeExtentComponent(extentComponent: YExtentComponent): void;
|
|
90
|
+
/**
|
|
91
|
+
* Create new pane extent and attach data series to it
|
|
92
|
+
*/
|
|
93
|
+
moveDataSeriesToNewExtentComponent(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, align?: YAxisAlign): void;
|
|
94
|
+
/**
|
|
95
|
+
* Attach data series to existing y axis extent
|
|
96
|
+
*/
|
|
97
|
+
moveDataSeriesToExistingExtentComponent(dataSeries: DataSeriesModel[], initialPane: PaneComponent, initialExtent: YExtentComponent, extentComponent: YExtentComponent): void;
|
|
87
98
|
/**
|
|
88
99
|
* This method updates the view by calling the doAutoScale method of the scaleModel and firing the Draw event using the eventBus.
|
|
89
100
|
* @private
|
|
@@ -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 { Subject } from 'rxjs';
|
|
6
7
|
import { distinctUntilChanged } from 'rxjs/operators';
|
|
7
8
|
import { areBoundsChanged, CanvasElement, } from '../../canvas/canvas-bounds-container';
|
|
8
9
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
@@ -47,6 +48,7 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
47
48
|
this.hitTestCanvasModel = hitTestCanvasModel;
|
|
48
49
|
this.chartResizeHandler = chartResizeHandler;
|
|
49
50
|
this.yExtentComponents = [];
|
|
51
|
+
this.yExtentComponentsChangedSubject = new Subject();
|
|
50
52
|
this.getYAxisBounds = () => {
|
|
51
53
|
return this.canvasBoundsContainer.getBounds(CanvasElement.PANE_UUID_Y_AXIS(this.uuid));
|
|
52
54
|
};
|
|
@@ -84,8 +86,10 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
84
86
|
/**
|
|
85
87
|
* Creates a new GridComponent instance with the provided parameters.
|
|
86
88
|
* @param {string} uuid - The unique identifier of the pane.
|
|
87
|
-
* @param {ScaleModel}
|
|
88
|
-
* @param {
|
|
89
|
+
* @param {ScaleModel} scale - The scale model used to calculate the scale of the grid.
|
|
90
|
+
* @param {YAxisConfig} yAxisState - y Axis Config
|
|
91
|
+
* @param {() => NumericAxisLabel[]} yAxisLabelsGetter
|
|
92
|
+
* @param {() => Unit} yAxisBaselineGetter
|
|
89
93
|
* @returns {GridComponent} - The newly created GridComponent instance.
|
|
90
94
|
*/
|
|
91
95
|
createGridComponent(uuid, scale, yAxisState, yAxisLabelsGetter, yAxisBaselineGetter) {
|
|
@@ -97,8 +101,8 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
97
101
|
* Creates a handler for Y-axis panning of the chart.
|
|
98
102
|
* @private
|
|
99
103
|
* @param {string} uuid - The unique identifier of the chart pane.
|
|
100
|
-
* @param {ScaleModel}
|
|
101
|
-
* @returns
|
|
104
|
+
* @param {ScaleModel} scale - The scale model of the chart.
|
|
105
|
+
* @returns [Unsubscriber, DragNDropYComponent]
|
|
102
106
|
*/
|
|
103
107
|
createYPanHandler(uuid, scale) {
|
|
104
108
|
const chartPaneId = CanvasElement.PANE_UUID(uuid);
|
|
@@ -140,6 +144,7 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
140
144
|
yExtentComponent.activate();
|
|
141
145
|
this.yExtentComponents.push(yExtentComponent);
|
|
142
146
|
this.canvasBoundsContainer.updateYAxisWidths();
|
|
147
|
+
this.yExtentComponentsChangedSubject.next();
|
|
143
148
|
return yExtentComponent;
|
|
144
149
|
}
|
|
145
150
|
removeExtentComponent(extentComponent) {
|
|
@@ -148,6 +153,24 @@ export class PaneComponent extends ChartBaseElement {
|
|
|
148
153
|
// re-index extents
|
|
149
154
|
this.yExtentComponents.forEach((c, idx) => (c.idx = idx));
|
|
150
155
|
this.canvasBoundsContainer.updateYAxisWidths();
|
|
156
|
+
this.yExtentComponentsChangedSubject.next();
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Create new pane extent and attach data series to it
|
|
160
|
+
*/
|
|
161
|
+
moveDataSeriesToNewExtentComponent(dataSeries, initialPane, initialExtent, align = 'right') {
|
|
162
|
+
const extent = this.createExtentComponent();
|
|
163
|
+
extent.yAxis.setYAxisAlign(align);
|
|
164
|
+
dataSeries.forEach(series => series.moveToExtent(extent));
|
|
165
|
+
initialExtent.dataSeries.size === 0 && initialPane.removeExtentComponent(initialExtent);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Attach data series to existing y axis extent
|
|
169
|
+
*/
|
|
170
|
+
moveDataSeriesToExistingExtentComponent(dataSeries, initialPane, initialExtent, extentComponent) {
|
|
171
|
+
dataSeries.forEach(series => series.moveToExtent(extentComponent));
|
|
172
|
+
initialExtent.dataSeries.size === 0 && initialPane.removeExtentComponent(initialExtent);
|
|
173
|
+
this.yExtentComponentsChangedSubject.next();
|
|
151
174
|
}
|
|
152
175
|
/**
|
|
153
176
|
* This method updates the view by calling the doAutoScale method of the scaleModel and firing the Draw event using the eventBus.
|
|
@@ -14,6 +14,7 @@ import { CanvasInputListenerComponent } from '../../inputlisteners/canvas-input-
|
|
|
14
14
|
import { ChartPanComponent } from '../pan/chart-pan.component';
|
|
15
15
|
import { BoundsProvider } from '../../model/bounds.model';
|
|
16
16
|
import { HitTestCanvasModel } from '../../model/hit-test-canvas.model';
|
|
17
|
+
export declare const RESIZER_HIT_TEST_EXTENSION: number;
|
|
17
18
|
/**
|
|
18
19
|
* Bar separator between panes.
|
|
19
20
|
* Used to resize the areas height or just draw a fixed line.
|
|
@@ -9,6 +9,7 @@ import { DynamicDrawerType } from '../../drawers/drawing-manager';
|
|
|
9
9
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
10
10
|
import { DragNDropYComponent } from '../dran-n-drop_helper/drag-n-drop-y.component';
|
|
11
11
|
import { BarResizerDrawer } from './bar-resizer.drawer';
|
|
12
|
+
export const RESIZER_HIT_TEST_EXTENSION = 8;
|
|
12
13
|
/**
|
|
13
14
|
* Bar separator between panes.
|
|
14
15
|
* Used to resize the areas height or just draw a fixed line.
|
|
@@ -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
|
}
|
|
@@ -60,7 +60,8 @@ export declare class FancyYAxisLabelsModel extends ChartBaseElement {
|
|
|
60
60
|
* an easier way to manage custom y-axis labels, than y-axis labels providers, but doesn't support overlapping avoidance
|
|
61
61
|
*/
|
|
62
62
|
readonly customLabels: Record<string, VisualYAxisLabel>;
|
|
63
|
-
private
|
|
63
|
+
private _labelsProviders;
|
|
64
|
+
get labelsProviders(): Record<string, Record<string, YAxisLabelsProvider>>;
|
|
64
65
|
private labelsPositionRecalculatedSubject;
|
|
65
66
|
private animFrameId;
|
|
66
67
|
constructor(eventBus: EventBus, scale: ScaleModel, canvasBoundsContainer: CanvasBoundsContainer, state: YAxisConfig, canvasModel: CanvasModel, paneUUID: string, updateYAxisWidth: () => void, chartResizeHandler: ChartResizeHandler);
|
|
@@ -157,4 +158,5 @@ export declare class FancyYAxisLabelsModel extends ChartBaseElement {
|
|
|
157
158
|
*/
|
|
158
159
|
export interface YAxisLabelsProvider {
|
|
159
160
|
readonly getUnorderedLabels: () => LabelGroup[];
|
|
161
|
+
yAxisBoundsProvider?: () => Bounds;
|
|
160
162
|
}
|
|
@@ -27,6 +27,9 @@ export const LabelsGroups = {
|
|
|
27
27
|
* Anything but the base labels which are generated in other component {@link YAxisBaseLabelsModel}
|
|
28
28
|
*/
|
|
29
29
|
export class FancyYAxisLabelsModel extends ChartBaseElement {
|
|
30
|
+
get labelsProviders() {
|
|
31
|
+
return this._labelsProviders;
|
|
32
|
+
}
|
|
30
33
|
constructor(eventBus, scale, canvasBoundsContainer, state, canvasModel, paneUUID, updateYAxisWidth, chartResizeHandler) {
|
|
31
34
|
super();
|
|
32
35
|
this.eventBus = eventBus;
|
|
@@ -42,7 +45,7 @@ export class FancyYAxisLabelsModel extends ChartBaseElement {
|
|
|
42
45
|
* an easier way to manage custom y-axis labels, than y-axis labels providers, but doesn't support overlapping avoidance
|
|
43
46
|
*/
|
|
44
47
|
this.customLabels = {};
|
|
45
|
-
this.
|
|
48
|
+
this._labelsProviders = {};
|
|
46
49
|
this.labelsPositionRecalculatedSubject = new Subject();
|
|
47
50
|
this.animFrameId = `anim_cache_${uuid()}`;
|
|
48
51
|
this.initModel();
|