@devexperts/dxcharts-lite 2.0.2 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/chart/__tests__/chart.test.d.ts +6 -0
- package/dist/chart/__tests__/chart.test.js +51 -0
- package/dist/chart/__tests__/env.d.ts +5 -0
- package/dist/chart/__tests__/env.js +28 -0
- package/dist/chart/bootstrap.js +2 -2
- package/dist/chart/chart.config.d.ts +4 -1
- package/dist/chart/chart.config.js +1 -1
- package/dist/chart/components/chart/chart-base.model.d.ts +1 -1
- package/dist/chart/components/chart/chart.component.js +13 -3
- package/dist/chart/components/chart/chart.model.d.ts +2 -2
- package/dist/chart/components/chart/chart.model.js +9 -7
- package/dist/chart/components/cross_tool/cross-tool.component.d.ts +2 -1
- package/dist/chart/components/cross_tool/cross-tool.component.js +4 -3
- package/dist/chart/components/cross_tool/cross-tool.model.js +1 -0
- package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.d.ts +3 -1
- package/dist/chart/components/cross_tool/types/cross-and-labels.drawer.js +3 -2
- package/dist/chart/components/dynamic-objects/dynamic-objects.component.js +1 -1
- package/dist/chart/components/dynamic-objects/dynamic-objects.model.d.ts +30 -10
- package/dist/chart/components/dynamic-objects/dynamic-objects.model.js +119 -57
- package/dist/chart/components/grid/grid.drawer.js +3 -1
- package/dist/chart/components/pane/extent/y-extent-component.js +2 -1
- package/dist/chart/components/pane/pane-hit-test.controller.js +2 -2
- package/dist/chart/components/volumes/volumes.component.d.ts +3 -0
- package/dist/chart/components/volumes/volumes.component.js +21 -4
- package/dist/chart/components/volumes/volumes.model.d.ts +2 -0
- package/dist/chart/components/volumes/volumes.model.js +2 -0
- package/dist/chart/components/x_axis/x-axis.component.js +2 -2
- package/dist/chart/components/y_axis/label-color.functions.d.ts +2 -1
- package/dist/chart/components/y_axis/label-color.functions.js +17 -0
- package/dist/chart/components/y_axis/price_labels/data-series-y-axis-labels.provider.d.ts +2 -2
- package/dist/chart/components/y_axis/price_labels/data-series-y-axis-labels.provider.js +27 -25
- package/dist/chart/components/y_axis/price_labels/labels-positions-calculator.js +24 -13
- package/dist/chart/components/y_axis/price_labels/last-candle-labels.provider.d.ts +3 -3
- package/dist/chart/components/y_axis/price_labels/last-candle-labels.provider.js +58 -40
- package/dist/chart/components/y_axis/price_labels/y-axis-price-labels.drawer.d.ts +3 -3
- package/dist/chart/components/y_axis/price_labels/y-axis-price-labels.drawer.js +15 -13
- package/dist/chart/components/y_axis/y-axis-scale.handler.js +1 -1
- package/dist/chart/components/y_axis/y-axis.component.d.ts +2 -1
- package/dist/chart/components/y_axis/y-axis.component.js +6 -2
- package/dist/chart/drawers/ht-data-series.drawer.js +1 -1
- package/dist/chart/inputhandlers/cross-event-producer.component.js +2 -1
- package/dist/chart/inputhandlers/hover-producer.component.d.ts +1 -1
- package/dist/chart/inputhandlers/hover-producer.component.js +8 -8
- package/dist/chart/inputlisteners/canvas-input-listener.component.d.ts +12 -5
- package/dist/chart/inputlisteners/canvas-input-listener.component.js +74 -62
- package/dist/chart/model/candle-series.model.d.ts +1 -1
- package/dist/chart/model/candle-series.model.js +2 -2
- package/dist/chart/model/compare-series-hover.d.ts +2 -1
- package/dist/chart/model/compare-series-hover.js +1 -0
- package/dist/chart/model/data-series.model.d.ts +3 -2
- package/dist/chart/model/data-series.model.js +2 -1
- package/dist/chart/model/main-candle-series.model.d.ts +1 -1
- package/dist/chart/model/main-candle-series.model.js +2 -2
- package/dist/chart/model/scale.model.d.ts +2 -0
- package/dist/chart/model/scale.model.js +11 -2
- package/dist/chart/utils/dom.utils.d.ts +7 -0
- package/dist/chart/utils/dom.utils.js +12 -0
- package/dist/chart/utils/linkedList.utils.d.ts +3 -3
- package/dist/chart/utils/linkedList.utils.js +55 -57
- package/dist/dxchart.min.js +4 -4
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -8
- package/package.json +10 -4
|
@@ -7,25 +7,58 @@ import { BehaviorSubject } from 'rxjs';
|
|
|
7
7
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
8
8
|
import { LinkedList, ListNode } from '../../utils/linkedList.utils';
|
|
9
9
|
export class DynamicObjectsModel extends ChartBaseElement {
|
|
10
|
-
constructor() {
|
|
10
|
+
constructor(canvasModel) {
|
|
11
11
|
super();
|
|
12
|
-
this.
|
|
12
|
+
this.canvasModel = canvasModel;
|
|
13
|
+
this.modelIdToObjectMap = new Map();
|
|
13
14
|
this._objects = new BehaviorSubject({});
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* @returns the `DynamicObject` itself and pane `LinkedList` where the object is stored.
|
|
18
|
+
*
|
|
19
|
+
*/
|
|
20
|
+
getObjectInfoById(id) {
|
|
21
|
+
const obj = this.modelIdToObjectMap.get(id);
|
|
22
|
+
if (!obj) {
|
|
23
|
+
return undefined;
|
|
24
|
+
}
|
|
25
|
+
const paneId = obj.paneId;
|
|
26
|
+
const objects = this.objects;
|
|
27
|
+
const paneList = objects[paneId];
|
|
28
|
+
if (!paneList) {
|
|
29
|
+
return undefined;
|
|
30
|
+
}
|
|
31
|
+
return [obj, paneList];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* @returns `DynamicObject` position in associated pane `LinkedList`
|
|
35
|
+
* @returns `-1` if an object was not found
|
|
36
|
+
*
|
|
37
|
+
*/
|
|
38
|
+
getObjectPosition(id) {
|
|
39
|
+
const objInfo = this.getObjectInfoById(id);
|
|
40
|
+
if (!objInfo) {
|
|
41
|
+
return -1;
|
|
42
|
+
}
|
|
43
|
+
const [obj, paneList] = objInfo;
|
|
44
|
+
const targetNode = new ListNode(obj);
|
|
45
|
+
return paneList.getNodePosition(targetNode);
|
|
46
|
+
}
|
|
15
47
|
/**
|
|
16
48
|
* Adds an object from outside chart-core into model
|
|
17
49
|
* @param obj
|
|
18
50
|
* @param paneId
|
|
19
51
|
*/
|
|
20
|
-
addObject(obj
|
|
52
|
+
addObject(obj) {
|
|
21
53
|
var _a;
|
|
54
|
+
const paneId = obj.paneId;
|
|
22
55
|
const objects = this.objects;
|
|
23
56
|
const paneList = (_a = objects[paneId]) !== null && _a !== void 0 ? _a : new LinkedList();
|
|
24
57
|
if (!Object.keys(objects).find(pane => pane === paneId)) {
|
|
25
58
|
objects[paneId] = paneList;
|
|
26
59
|
}
|
|
27
60
|
paneList.insertAtEnd(obj);
|
|
28
|
-
this.
|
|
61
|
+
this.modelIdToObjectMap.set(obj.id, obj);
|
|
29
62
|
this.setDynamicObjects(objects);
|
|
30
63
|
}
|
|
31
64
|
/**
|
|
@@ -33,36 +66,61 @@ export class DynamicObjectsModel extends ChartBaseElement {
|
|
|
33
66
|
* @param model
|
|
34
67
|
* @param paneId
|
|
35
68
|
*/
|
|
36
|
-
removeObject(
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.setDynamicObjects(objects);
|
|
69
|
+
removeObject(id) {
|
|
70
|
+
const objInfo = this.getObjectInfoById(id);
|
|
71
|
+
if (!objInfo) {
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const [obj, paneList] = objInfo;
|
|
75
|
+
const targetNode = new ListNode(obj);
|
|
76
|
+
const targetPos = paneList.getNodePosition(targetNode);
|
|
77
|
+
paneList.removeAt(targetPos);
|
|
78
|
+
this.modelIdToObjectMap.delete(id);
|
|
79
|
+
if (paneList.size() === 0) {
|
|
80
|
+
delete this.objects[obj.paneId];
|
|
49
81
|
}
|
|
82
|
+
this.setDynamicObjects(this.objects);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Moves the object inside the associated LinkedList to the specified position
|
|
86
|
+
*/
|
|
87
|
+
moveToPosition(id, position) {
|
|
88
|
+
const objInfo = this.getObjectInfoById(id);
|
|
89
|
+
if (!objInfo) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const [obj, paneList] = objInfo;
|
|
93
|
+
const node = new ListNode(obj);
|
|
94
|
+
const currentPos = paneList.getNodePosition(node);
|
|
95
|
+
if (currentPos === position) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
if (currentPos < position) {
|
|
99
|
+
paneList.insertAt(position, obj);
|
|
100
|
+
paneList.removeAt(currentPos);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
paneList.removeAt(currentPos);
|
|
104
|
+
paneList.insertAt(position, obj);
|
|
105
|
+
}
|
|
106
|
+
this.setDynamicObjects(this.objects);
|
|
50
107
|
}
|
|
51
108
|
/**
|
|
52
109
|
* Moves the object inside the drawing order so it's being drawn before the other elements
|
|
53
110
|
* @param paneId
|
|
54
111
|
* @param listNode
|
|
55
112
|
*/
|
|
56
|
-
bringToFront(
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
113
|
+
bringToFront(id) {
|
|
114
|
+
const objInfo = this.getObjectInfoById(id);
|
|
115
|
+
if (!objInfo) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
const [obj, paneList] = objInfo;
|
|
119
|
+
const targetNode = new ListNode(obj);
|
|
120
|
+
const targetPos = paneList.getNodePosition(targetNode);
|
|
121
|
+
if (targetPos >= 0 && targetPos < paneList.size()) {
|
|
122
|
+
paneList.removeAt(targetPos);
|
|
123
|
+
paneList.insertAtEnd(obj);
|
|
66
124
|
this.setDynamicObjects(this.objects);
|
|
67
125
|
}
|
|
68
126
|
}
|
|
@@ -71,16 +129,17 @@ export class DynamicObjectsModel extends ChartBaseElement {
|
|
|
71
129
|
* @param paneId
|
|
72
130
|
* @param listNode
|
|
73
131
|
*/
|
|
74
|
-
bringToBack(
|
|
75
|
-
const
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
132
|
+
bringToBack(id) {
|
|
133
|
+
const objInfo = this.getObjectInfoById(id);
|
|
134
|
+
if (!objInfo) {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const [obj, paneList] = objInfo;
|
|
138
|
+
const targetNode = new ListNode(obj);
|
|
139
|
+
const targetPos = paneList.getNodePosition(targetNode);
|
|
140
|
+
if (targetPos > 0 && targetPos <= paneList.size()) {
|
|
141
|
+
paneList.removeAt(targetPos);
|
|
142
|
+
paneList.insertAt(0, obj);
|
|
84
143
|
this.setDynamicObjects(this.objects);
|
|
85
144
|
}
|
|
86
145
|
}
|
|
@@ -89,16 +148,17 @@ export class DynamicObjectsModel extends ChartBaseElement {
|
|
|
89
148
|
* @param obj
|
|
90
149
|
* @param paneId
|
|
91
150
|
*/
|
|
92
|
-
moveForward(
|
|
93
|
-
const
|
|
94
|
-
if (
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
151
|
+
moveForward(id) {
|
|
152
|
+
const objInfo = this.getObjectInfoById(id);
|
|
153
|
+
if (!objInfo) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const [obj, paneList] = objInfo;
|
|
157
|
+
const targetNode = new ListNode(obj);
|
|
158
|
+
const targetPos = paneList.getNodePosition(targetNode);
|
|
159
|
+
if (targetPos >= 0 && targetPos + 1 < paneList.size()) {
|
|
160
|
+
paneList.removeAt(targetPos);
|
|
161
|
+
paneList.insertAt(targetPos + 1, obj);
|
|
102
162
|
this.setDynamicObjects(this.objects);
|
|
103
163
|
}
|
|
104
164
|
}
|
|
@@ -107,16 +167,17 @@ export class DynamicObjectsModel extends ChartBaseElement {
|
|
|
107
167
|
* @param obj
|
|
108
168
|
* @param paneId
|
|
109
169
|
*/
|
|
110
|
-
moveBackwards(
|
|
111
|
-
const
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
170
|
+
moveBackwards(id) {
|
|
171
|
+
const objInfo = this.getObjectInfoById(id);
|
|
172
|
+
if (!objInfo) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
const [obj, paneList] = objInfo;
|
|
176
|
+
const targetNode = new ListNode(obj);
|
|
177
|
+
const targetPos = paneList.getNodePosition(targetNode);
|
|
178
|
+
if (targetPos > 0 && targetPos < paneList.size()) {
|
|
179
|
+
paneList.removeAt(targetPos);
|
|
180
|
+
paneList.insertAt(targetPos - 1, obj);
|
|
120
181
|
this.setDynamicObjects(this.objects);
|
|
121
182
|
}
|
|
122
183
|
}
|
|
@@ -132,5 +193,6 @@ export class DynamicObjectsModel extends ChartBaseElement {
|
|
|
132
193
|
*/
|
|
133
194
|
setDynamicObjects(objects) {
|
|
134
195
|
this._objects.next(objects);
|
|
196
|
+
this.canvasModel.fireDraw();
|
|
135
197
|
}
|
|
136
198
|
}
|
|
@@ -40,9 +40,11 @@ export class GridDrawer {
|
|
|
40
40
|
* @param {CanvasRenderingContext2D} ctx - The 2D rendering context of the canvas element.
|
|
41
41
|
*/
|
|
42
42
|
drawZeroLine(ctx) {
|
|
43
|
+
const yAxisLabels = this.yLabelsProvider();
|
|
43
44
|
if (this.getBaseline &&
|
|
44
45
|
this.yAxisState.type === 'percent' &&
|
|
45
|
-
this.yAxisState.zeroPercentLine
|
|
46
|
+
this.yAxisState.zeroPercentLine &&
|
|
47
|
+
yAxisLabels.length) {
|
|
46
48
|
const bounds = this.xBoundsProvider();
|
|
47
49
|
const y = floor(this.getBaseline());
|
|
48
50
|
ctx.beginPath();
|
|
@@ -7,6 +7,7 @@ import { CanvasElement } from '../../../canvas/canvas-bounds-container';
|
|
|
7
7
|
import { ChartBaseElement } from '../../../model/chart-base-element';
|
|
8
8
|
import { DataSeriesModel, VisualSeriesPoint, defaultValueFormatter, } from '../../../model/data-series.model';
|
|
9
9
|
import { mergeHighLow } from '../../../model/scaling/auto-scale.model';
|
|
10
|
+
import { uuid } from '../../../utils/uuid.utils';
|
|
10
11
|
import { createYExtentFormatters } from '../../chart/price.formatter';
|
|
11
12
|
export class YExtentComponent extends ChartBaseElement {
|
|
12
13
|
constructor(paneUUID, idx, paneComponent, chartBaseModel, canvasBoundsContainer, hitTestController, dynamicObjectsCanvasModel, scale, createYAxisComponent, dragNDrop, dataSeries = new Set(), formatters = {
|
|
@@ -66,7 +67,7 @@ export class YExtentComponent extends ChartBaseElement {
|
|
|
66
67
|
* @returns {DataSeriesModel} - The newly created DataSeriesModel object.
|
|
67
68
|
*/
|
|
68
69
|
createDataSeries() {
|
|
69
|
-
const series = new DataSeriesModel(this, this.hitTestController.getNewDataSeriesHitTestId());
|
|
70
|
+
const series = new DataSeriesModel(this, uuid(), this.hitTestController.getNewDataSeriesHitTestId());
|
|
70
71
|
series.toVisualPoints = this.toVisualPoints;
|
|
71
72
|
return series;
|
|
72
73
|
}
|
|
@@ -32,7 +32,7 @@ export class PaneHitTestController {
|
|
|
32
32
|
* @returns {DataSeriesModel | undefined} - The data series with the given ID, or undefined if it does not exist.
|
|
33
33
|
*/
|
|
34
34
|
lookup(id) {
|
|
35
|
-
const result = this.allDataSeries.find(d => d.
|
|
35
|
+
const result = this.allDataSeries.find(d => d.htId === id);
|
|
36
36
|
return result;
|
|
37
37
|
}
|
|
38
38
|
/**
|
|
@@ -41,7 +41,7 @@ export class PaneHitTestController {
|
|
|
41
41
|
* @returns {void}
|
|
42
42
|
*/
|
|
43
43
|
onHover(model) {
|
|
44
|
-
this.allDataSeries.forEach(d => (d.hovered = d.
|
|
44
|
+
this.allDataSeries.forEach(d => (d.hovered = d.htId === (model === null || model === void 0 ? void 0 : model.htId)));
|
|
45
45
|
this.canvasModel.fireDraw();
|
|
46
46
|
}
|
|
47
47
|
onMouseDown(model) {
|
|
@@ -21,9 +21,11 @@ export declare class VolumesComponent extends ChartBaseElement {
|
|
|
21
21
|
private canvasModel;
|
|
22
22
|
private canvasBoundsContainer;
|
|
23
23
|
private config;
|
|
24
|
+
private dynamicObjectsComponent;
|
|
24
25
|
separateVolumes: SeparateVolumesComponent;
|
|
25
26
|
volumesColorByChartTypeMap: Partial<Record<BarType, VolumeColorResolver>>;
|
|
26
27
|
volumesModel: VolumesModel;
|
|
28
|
+
private readonly volumesDrawer;
|
|
27
29
|
volumeVisibilityChangedSubject: BehaviorSubject<boolean>;
|
|
28
30
|
volumeIsSeparateModeChangedSubject: BehaviorSubject<boolean>;
|
|
29
31
|
constructor(canvasModel: CanvasModel, chartComponent: ChartComponent, scale: ScaleModel, canvasBoundsContainer: CanvasBoundsContainer, drawingManager: DrawingManager, config: FullChartConfig, paneManager: PaneManager, dynamicObjectsComponent: DynamicObjectsComponent);
|
|
@@ -56,4 +58,5 @@ export declare class VolumesComponent extends ChartBaseElement {
|
|
|
56
58
|
* @returns {void}
|
|
57
59
|
*/
|
|
58
60
|
setVisible(visible?: boolean): void;
|
|
61
|
+
private addVolumesToDynamicObjects;
|
|
59
62
|
}
|
|
@@ -9,13 +9,14 @@ import { ChartBaseElement } from '../../model/chart-base-element';
|
|
|
9
9
|
import { SeparateVolumesComponent } from './separate-volumes.component';
|
|
10
10
|
import { resolveColorForBar, resolveColorForCandle, resolveColorForLine } from './volume-color-resolvers.functions';
|
|
11
11
|
import { VolumesDrawer } from './volumes.drawer';
|
|
12
|
-
import { VolumesModel } from './volumes.model';
|
|
12
|
+
import { VOLUMES_UUID, VolumesModel } from './volumes.model';
|
|
13
13
|
export class VolumesComponent extends ChartBaseElement {
|
|
14
14
|
constructor(canvasModel, chartComponent, scale, canvasBoundsContainer, drawingManager, config, paneManager, dynamicObjectsComponent) {
|
|
15
15
|
super();
|
|
16
16
|
this.canvasModel = canvasModel;
|
|
17
17
|
this.canvasBoundsContainer = canvasBoundsContainer;
|
|
18
18
|
this.config = config;
|
|
19
|
+
this.dynamicObjectsComponent = dynamicObjectsComponent;
|
|
19
20
|
this.volumesColorByChartTypeMap = {};
|
|
20
21
|
this.volumeVisibilityChangedSubject = new BehaviorSubject(false);
|
|
21
22
|
this.volumeIsSeparateModeChangedSubject = new BehaviorSubject(false);
|
|
@@ -23,8 +24,8 @@ export class VolumesComponent extends ChartBaseElement {
|
|
|
23
24
|
this.volumesModel = volumesModel;
|
|
24
25
|
this.addChildEntity(volumesModel);
|
|
25
26
|
this.separateVolumes = new SeparateVolumesComponent(chartComponent, drawingManager, config, volumesModel, paneManager);
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
this.volumesDrawer = new VolumesDrawer(config, this.volumesModel, chartComponent.chartModel, () => { var _a, _b; return (this.config.components.volumes.showSeparately ? (_b = (_a = this.separateVolumes.pane) === null || _a === void 0 ? void 0 : _a.scale) !== null && _b !== void 0 ? _b : scale : scale); }, this.volumesColorByChartTypeMap, () => true);
|
|
28
|
+
config.components.volumes.visible && this.addVolumesToDynamicObjects();
|
|
28
29
|
this.addChildEntity(this.separateVolumes);
|
|
29
30
|
this.registerDefaultVolumeColorResolvers();
|
|
30
31
|
this.volumeVisibilityChangedSubject.next(config.components.volumes.visible);
|
|
@@ -83,7 +84,10 @@ export class VolumesComponent extends ChartBaseElement {
|
|
|
83
84
|
setVisible(visible = true) {
|
|
84
85
|
this.config.components.volumes.visible = visible;
|
|
85
86
|
this.volumeVisibilityChangedSubject.next(visible);
|
|
86
|
-
|
|
87
|
+
visible
|
|
88
|
+
? this.addVolumesToDynamicObjects()
|
|
89
|
+
: this.dynamicObjectsComponent.model.removeObject(this.volumesModel.id);
|
|
90
|
+
if (this.config.components.volumes.showSeparately) {
|
|
87
91
|
if (visible) {
|
|
88
92
|
this.separateVolumes.activateSeparateVolumes();
|
|
89
93
|
this.volumeIsSeparateModeChangedSubject.next(true);
|
|
@@ -96,4 +100,17 @@ export class VolumesComponent extends ChartBaseElement {
|
|
|
96
100
|
this.canvasBoundsContainer.recalculatePanesHeightRatios();
|
|
97
101
|
this.canvasModel.fireDraw();
|
|
98
102
|
}
|
|
103
|
+
addVolumesToDynamicObjects() {
|
|
104
|
+
// check if the volumes dynamic object is already added
|
|
105
|
+
const position = this.dynamicObjectsComponent.model.getObjectPosition(this.volumesModel.id);
|
|
106
|
+
if (position !== -1) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
this.dynamicObjectsComponent.model.addObject({
|
|
110
|
+
id: this.volumesModel.id,
|
|
111
|
+
paneId: this.config.components.volumes.showSeparately ? VOLUMES_UUID : CHART_UUID,
|
|
112
|
+
drawer: this.volumesDrawer,
|
|
113
|
+
model: this.volumesModel,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
99
116
|
}
|
|
@@ -8,9 +8,11 @@ import { ChartBaseElement } from '../../model/chart-base-element';
|
|
|
8
8
|
import { ScaleModel } from '../../model/scale.model';
|
|
9
9
|
import { HighLowProvider } from '../../model/scaling/auto-scale.model';
|
|
10
10
|
import { ChartComponent } from '../chart/chart.component';
|
|
11
|
+
export declare const VOLUMES_UUID = "volumes";
|
|
11
12
|
export declare class VolumesModel extends ChartBaseElement {
|
|
12
13
|
private chartComponent;
|
|
13
14
|
private scale;
|
|
15
|
+
readonly id = "volumes";
|
|
14
16
|
volumeMax: BehaviorSubject<number>;
|
|
15
17
|
highLowProvider: HighLowProvider;
|
|
16
18
|
constructor(chartComponent: ChartComponent, scale: ScaleModel);
|
|
@@ -7,11 +7,13 @@ import { BehaviorSubject, merge } from 'rxjs';
|
|
|
7
7
|
import { ChartBaseElement } from '../../model/chart-base-element';
|
|
8
8
|
import { firstOf, maxMin } from '../../utils/array.utils';
|
|
9
9
|
const volumeMaxMinFn = maxMin(candle => candle.candle.volume);
|
|
10
|
+
export const VOLUMES_UUID = 'volumes';
|
|
10
11
|
export class VolumesModel extends ChartBaseElement {
|
|
11
12
|
constructor(chartComponent, scale) {
|
|
12
13
|
super();
|
|
13
14
|
this.chartComponent = chartComponent;
|
|
14
15
|
this.scale = scale;
|
|
16
|
+
this.id = VOLUMES_UUID;
|
|
15
17
|
// max volume in all data series
|
|
16
18
|
this.volumeMax = new BehaviorSubject(0);
|
|
17
19
|
this.highLowProvider = {
|
|
@@ -56,8 +56,8 @@ export class XAxisComponent extends ChartBaseElement {
|
|
|
56
56
|
this.xAxisLabelsGenerator.generateLabels();
|
|
57
57
|
}));
|
|
58
58
|
this.addRxSubscription(this.chartComponent.chartModel.candlesPrependSubject
|
|
59
|
-
.pipe(filter(({
|
|
60
|
-
return this.chartComponent.chartModel.mainCandleSeries.visualPoints.slice(0,
|
|
59
|
+
.pipe(filter(({ prependedCandles }) => prependedCandles.length !== 0), map(({ prependedCandles }) => {
|
|
60
|
+
return this.chartComponent.chartModel.mainCandleSeries.visualPoints.slice(0, prependedCandles.length);
|
|
61
61
|
}))
|
|
62
62
|
.subscribe(newCandles => {
|
|
63
63
|
//@ts-ignore
|
|
@@ -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
|
import { PriceMovement } from '../../model/candle-series.model';
|
|
7
|
-
import { FullChartColors, YAxisLabelsColors } from '../../chart.config';
|
|
7
|
+
import { FullChartColors, YAxisConfig, YAxisLabelsColors } from '../../chart.config';
|
|
8
8
|
export declare const DEFAULT_LABEL_COLOR = "#FF00FF";
|
|
9
|
+
export declare function getPlainLabelTextColor(colorsConfig: FullChartColors, textColor: string, invertedTextColor: string, yAxisState: YAxisConfig): string;
|
|
9
10
|
export declare const getPrimaryLabelTextColor: (lastPriceMovement: PriceMovement, colors: YAxisLabelsColors) => string;
|
|
10
11
|
export declare const resolveColorForBar: (priceMovement: PriceMovement, colors: FullChartColors) => string;
|
|
11
12
|
export declare const resolveColorForLine: (priceMovement: PriceMovement, colors: FullChartColors) => string;
|
|
@@ -3,7 +3,24 @@
|
|
|
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 { getLabelTextColorByBackgroundColor } from '../../utils/canvas/canvas-text-functions.utils';
|
|
6
7
|
export const DEFAULT_LABEL_COLOR = '#FF00FF';
|
|
8
|
+
export function getPlainLabelTextColor(colorsConfig, textColor, invertedTextColor, yAxisState) {
|
|
9
|
+
// `plain` label is transparent, so to calculate text color
|
|
10
|
+
// we need to go down to draw hierarchy
|
|
11
|
+
// the next is YAxis bg color
|
|
12
|
+
const yAxisBGColor = colorsConfig.yAxis.backgroundColor;
|
|
13
|
+
// if yAxis bg color is transparent, then we need to check chart area background color
|
|
14
|
+
const plainChartBGColor = colorsConfig.chartAreaTheme.backgroundColor;
|
|
15
|
+
// when chart area bg color is gradient, then we need to check which side yAxis is drawn
|
|
16
|
+
// because color on the right side and left side is different
|
|
17
|
+
const leftChartBGColor = colorsConfig.chartAreaTheme.backgroundGradientTopColor;
|
|
18
|
+
const rightChartBGColor = colorsConfig.chartAreaTheme.backgroundGradientBottomColor;
|
|
19
|
+
const gradientChartBGColor = yAxisState.align === 'left' ? leftChartBGColor : rightChartBGColor;
|
|
20
|
+
const chartBGColor = colorsConfig.chartAreaTheme.backgroundMode === 'gradient' ? gradientChartBGColor : plainChartBGColor;
|
|
21
|
+
const bgColor = yAxisBGColor === 'transparent' ? chartBGColor : yAxisBGColor;
|
|
22
|
+
return getLabelTextColorByBackgroundColor(bgColor, textColor, invertedTextColor);
|
|
23
|
+
}
|
|
7
24
|
export const getPrimaryLabelTextColor = (lastPriceMovement, colors) => {
|
|
8
25
|
if (lastPriceMovement === 'down') {
|
|
9
26
|
return colors.lastPrice.textNegative;
|
|
@@ -12,8 +12,8 @@ export declare class DataSeriesYAxisLabelsProvider implements YAxisLabelsProvide
|
|
|
12
12
|
private series;
|
|
13
13
|
private config;
|
|
14
14
|
yAxisBoundsProvider: BoundsProvider;
|
|
15
|
-
axisState
|
|
16
|
-
constructor(series: DataSeriesModel, config: DataSeriesConfig, yAxisBoundsProvider: BoundsProvider, axisState
|
|
15
|
+
axisState: YAxisConfig;
|
|
16
|
+
constructor(series: DataSeriesModel, config: DataSeriesConfig, yAxisBoundsProvider: BoundsProvider, axisState: YAxisConfig);
|
|
17
17
|
/**
|
|
18
18
|
* Returns an array of LabelGroup objects that contain VisualYAxisLabel objects.
|
|
19
19
|
* The labels are unordered and are based on the last data series point or the last visual series point, depending on the configuration.
|
|
@@ -21,32 +21,34 @@ export class DataSeriesYAxisLabelsProvider {
|
|
|
21
21
|
*/
|
|
22
22
|
getUnorderedLabels() {
|
|
23
23
|
const visible = this.config.visible;
|
|
24
|
-
if (visible) {
|
|
25
|
-
|
|
26
|
-
? this.series.getLastDataSeriesPoint
|
|
27
|
-
: this.series.getLastVisualSeriesPoint;
|
|
28
|
-
const bounds = this.yAxisBoundsProvider();
|
|
29
|
-
const mode = this.config.labelMode;
|
|
30
|
-
const appearanceType = this.config.labelAppearanceType;
|
|
31
|
-
const lastPoint = getLastPointForLabel();
|
|
32
|
-
if (lastPoint !== undefined) {
|
|
33
|
-
const lastPointY = this.series.view.toY(lastPoint.close);
|
|
34
|
-
if (isFinite(lastPointY)) {
|
|
35
|
-
const label = this.series.valueFormatter(lastPoint.close);
|
|
36
|
-
const drawConfig = this.getLabelDrawConfig();
|
|
37
|
-
return [
|
|
38
|
-
{
|
|
39
|
-
labels: [
|
|
40
|
-
Object.assign({ y: lastPointY, description: this.series.name, mode, labelType: appearanceType, labelText: label }, drawConfig),
|
|
41
|
-
],
|
|
42
|
-
axisState: this.axisState,
|
|
43
|
-
bounds,
|
|
44
|
-
},
|
|
45
|
-
];
|
|
46
|
-
}
|
|
47
|
-
}
|
|
24
|
+
if (!visible) {
|
|
25
|
+
return [];
|
|
48
26
|
}
|
|
49
|
-
|
|
27
|
+
const getLastPointForLabel = this.config.labelLastValue === 'series'
|
|
28
|
+
? this.series.getLastDataSeriesPoint
|
|
29
|
+
: this.series.getLastVisualSeriesPoint;
|
|
30
|
+
const bounds = this.yAxisBoundsProvider();
|
|
31
|
+
const mode = this.config.labelMode;
|
|
32
|
+
const appearanceType = this.config.labelAppearanceType;
|
|
33
|
+
const lastPoint = getLastPointForLabel();
|
|
34
|
+
if (lastPoint === undefined) {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
const lastPointY = this.series.view.toY(lastPoint.close);
|
|
38
|
+
if (!isFinite(lastPointY)) {
|
|
39
|
+
return [];
|
|
40
|
+
}
|
|
41
|
+
const label = this.series.valueFormatter(lastPoint.close);
|
|
42
|
+
const drawConfig = this.getLabelDrawConfig();
|
|
43
|
+
return [
|
|
44
|
+
{
|
|
45
|
+
labels: [
|
|
46
|
+
Object.assign({ y: lastPointY, description: this.series.name, mode, labelType: appearanceType, labelText: label }, drawConfig),
|
|
47
|
+
],
|
|
48
|
+
axisState: this.axisState,
|
|
49
|
+
bounds,
|
|
50
|
+
},
|
|
51
|
+
];
|
|
50
52
|
}
|
|
51
53
|
/**
|
|
52
54
|
* Retrieves the `config` object from the `series` object and then retrieves the `paintConfig` object from the `config` object.
|
|
@@ -21,23 +21,34 @@ export function calcLabelsYCoordinates(points, labelHeight) {
|
|
|
21
21
|
.filter(notEmpty)
|
|
22
22
|
.sort(sortLabels); // sort labels in ascending order, top -> down
|
|
23
23
|
const newCoordinates = new Array(formattedCoordinates.length);
|
|
24
|
-
formattedCoordinates.
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const lowestWeight = formattedCoordinates.reduce((acc, curr) => Math.min(acc, curr.labelWeight), Number.POSITIVE_INFINITY);
|
|
25
|
+
const lowestWeightIndex = formattedCoordinates.findIndex(x => x.labelWeight === lowestWeight);
|
|
26
|
+
for (let i = lowestWeightIndex; i >= 0; i--) {
|
|
27
|
+
const current = formattedCoordinates[i];
|
|
28
|
+
const prev = formattedCoordinates[i - 1];
|
|
29
|
+
if (!current) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
if (prev && prev.bottom > current.top) {
|
|
33
|
+
const paddingAdjust = Math.abs(prev.labelWeight - current.labelWeight) === 1 ? 2 : 0;
|
|
34
|
+
prev.bottom = current.top - paddingAdjust;
|
|
35
|
+
prev.top = prev.bottom - labelHeight;
|
|
36
|
+
}
|
|
37
|
+
newCoordinates[current.actualIndex] = (current.top + current.bottom) / 2;
|
|
38
|
+
}
|
|
39
|
+
for (let i = lowestWeightIndex; i < formattedCoordinates.length; i++) {
|
|
40
|
+
const current = formattedCoordinates[i];
|
|
41
|
+
const next = formattedCoordinates[i + 1];
|
|
42
|
+
if (!current) {
|
|
43
|
+
break;
|
|
27
44
|
}
|
|
28
|
-
const next = formattedCoordinates[idx + 1];
|
|
29
45
|
if (next && next.top < current.bottom) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*/
|
|
34
|
-
const paddingAdjust = next.labelWeight - current.labelWeight === 1 ? 2 : 0;
|
|
35
|
-
const delta = current.bottom - next.top + paddingAdjust;
|
|
36
|
-
next.top += delta;
|
|
37
|
-
next.bottom += delta;
|
|
46
|
+
const paddingAdjust = Math.abs(next.labelWeight - current.labelWeight) === 1 ? 2 : 0;
|
|
47
|
+
next.top = current.bottom + paddingAdjust;
|
|
48
|
+
next.bottom = next.top + labelHeight;
|
|
38
49
|
}
|
|
39
50
|
newCoordinates[current.actualIndex] = (current.top + current.bottom) / 2;
|
|
40
|
-
}
|
|
51
|
+
}
|
|
41
52
|
return newCoordinates;
|
|
42
53
|
}
|
|
43
54
|
const toLabel = (point, index, labelHeight) => point
|
|
@@ -10,11 +10,11 @@ import { LabelGroup, YAxisLabelsProvider } from './y-axis-labels.model';
|
|
|
10
10
|
import { LabelColorResolver } from '../y-axis.component';
|
|
11
11
|
export declare class LastCandleLabelsProvider implements YAxisLabelsProvider {
|
|
12
12
|
private chartModel;
|
|
13
|
-
private
|
|
13
|
+
private chartConfig;
|
|
14
14
|
private yAxisConfig;
|
|
15
15
|
private lastCandleLabelsByChartType;
|
|
16
16
|
private resolveLabelColorFn;
|
|
17
|
-
constructor(chartModel: ChartModel,
|
|
17
|
+
constructor(chartModel: ChartModel, chartConfig: FullChartConfig, yAxisConfig: YAxisConfig, lastCandleLabelsByChartType: Partial<Record<DataSeriesType, LastCandleLabelHandler>>, resolveLabelColorFn: (chartType: DataSeriesType) => LabelColorResolver);
|
|
18
18
|
/**
|
|
19
19
|
* Returns an array of LabelGroup objects that contain the labels for the yAxis of the chart.
|
|
20
20
|
* @returns {LabelGroup[]} An array of LabelGroup objects that contain the labels for the yAxis of the chart.
|
|
@@ -29,7 +29,7 @@ export declare class LastCandleLabelsProvider implements YAxisLabelsProvider {
|
|
|
29
29
|
/**
|
|
30
30
|
* Returns the configuration object for drawing the label of the Y-axis.
|
|
31
31
|
* @param {CandleSeriesModel} series - The series model for which the label configuration is to be returned.
|
|
32
|
-
* @param {boolean} primary - A boolean value indicating whether the label is
|
|
32
|
+
* @param {boolean} primary - A boolean value indicating whether the label is for the main series or not.
|
|
33
33
|
* @returns {YAxisLabelDrawConfig} - The configuration object for drawing the label of the Y-axis.
|
|
34
34
|
*/
|
|
35
35
|
private getLabelDrawConfig;
|