@oliasoft-open-source/charts-library 2.16.0-beta-3 → 2.17.0-beta-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/index.js +1 -0
- package/package.json +1 -1
- package/release-notes.md +2 -2
- package/src/components/line-chart/constants/line-chart-consts.js +3 -0
- package/src/components/line-chart/hooks/use-chart-options.js +0 -22
- package/src/components/line-chart/line-chart-prop-types.js +3 -33
- package/src/components/line-chart/line-chart.jsx +10 -12
- package/src/components/line-chart/utils/initialize/initialize-line-chart.js +28 -0
- package/src/helpers/chart-interface.ts +4 -9
- package/src/helpers/chart-utils.js +1 -1
- package/src/helpers/get-chart-annotation.js +44 -7
- package/src/components/line-chart/plugins/chart-area-text-plugin.js +0 -267
- package/src/components/line-chart/plugins/plugin-constants.js +0 -11
- /package/src/components/line-chart/{plugins/line-chart.minor-gridlines-plugin.js → line-chart.minor-gridlines-plugin.js} +0 -0
package/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import ScatterChart from './src/components/scatter-chart/scatter-chart';
|
|
6
6
|
|
|
7
7
|
export { LineChart } from './src/components/line-chart/line-chart';
|
|
8
|
+
export { initializeLineChart } from './src/components/line-chart/utils/initialize/initialize-line-chart';
|
|
8
9
|
|
|
9
10
|
export { PieChart } from './src/components/pie-chart/pie-chart';
|
|
10
11
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oliasoft-open-source/charts-library",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.17.0-beta-1",
|
|
4
4
|
"description": "React Chart Library (based on Chart.js and react-chart-js-2)",
|
|
5
5
|
"homepage": "https://gitlab.com/oliasoft-open-source/charts-library",
|
|
6
6
|
"bugs": {
|
package/release-notes.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Charts Library Release Notes
|
|
2
2
|
|
|
3
|
-
## 2.
|
|
4
|
-
- Added
|
|
3
|
+
## 2.17.0
|
|
4
|
+
- Added initialize logic, for improve translations
|
|
5
5
|
|
|
6
6
|
## 2.15.0
|
|
7
7
|
- Added translation, by provider handled([OW-11237](https://oliasoft.atlassian.net/browse/OW-11237))
|
|
@@ -6,3 +6,6 @@ export const DEFAULT_LINE_POINT_RADIUS = 0;
|
|
|
6
6
|
export const DEFAULT_BACKGROUND_COLOR = 'transparent';
|
|
7
7
|
export const ZOOM_BOX_BACKGROUND_COLOR = 'rgba(0, 0, 0, 0.1)';
|
|
8
8
|
export const DOUBLE_CLICK = 'dblclick';
|
|
9
|
+
export const INIT_KEYS = {
|
|
10
|
+
TRANSLATIONS: 'translations',
|
|
11
|
+
};
|
|
@@ -38,18 +38,6 @@ export const useChartOptions = ({
|
|
|
38
38
|
}) => {
|
|
39
39
|
const {
|
|
40
40
|
interactions: { onAnimationComplete },
|
|
41
|
-
annotations: {
|
|
42
|
-
labelAnnotation: {
|
|
43
|
-
showLabel,
|
|
44
|
-
text,
|
|
45
|
-
position,
|
|
46
|
-
fontSize,
|
|
47
|
-
xOffset,
|
|
48
|
-
yOffset,
|
|
49
|
-
maxWidth,
|
|
50
|
-
lineHeight,
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
41
|
} = options;
|
|
54
42
|
|
|
55
43
|
const {
|
|
@@ -134,16 +122,6 @@ export const useChartOptions = ({
|
|
|
134
122
|
chartAreaBorder: {
|
|
135
123
|
borderColor: BORDER_COLOR,
|
|
136
124
|
},
|
|
137
|
-
chartAreaText: {
|
|
138
|
-
showLabel,
|
|
139
|
-
text,
|
|
140
|
-
position,
|
|
141
|
-
fontSize,
|
|
142
|
-
xOffset,
|
|
143
|
-
yOffset,
|
|
144
|
-
maxWidth,
|
|
145
|
-
lineHeight,
|
|
146
|
-
},
|
|
147
125
|
...dragData,
|
|
148
126
|
};
|
|
149
127
|
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import PropTypes from 'prop-types';
|
|
2
|
-
import { TextLabelPosition } from './plugins/plugin-constants';
|
|
3
2
|
|
|
4
3
|
export const LineChartPropTypes = {
|
|
5
4
|
table: PropTypes.node,
|
|
@@ -73,19 +72,7 @@ export const LineChartPropTypes = {
|
|
|
73
72
|
showMinorGridlines: PropTypes.bool,
|
|
74
73
|
}),
|
|
75
74
|
annotations: PropTypes.shape({
|
|
76
|
-
labelAnnotation: PropTypes.
|
|
77
|
-
showLabel: PropTypes.bool,
|
|
78
|
-
text: PropTypes.oneOfType([
|
|
79
|
-
PropTypes.string,
|
|
80
|
-
PropTypes.arrayOf(PropTypes.string),
|
|
81
|
-
]),
|
|
82
|
-
position: PropTypes.string,
|
|
83
|
-
fontSize: PropTypes.number,
|
|
84
|
-
xOffset: PropTypes.number,
|
|
85
|
-
yOffset: PropTypes.number,
|
|
86
|
-
maxWidth: PropTypes.number,
|
|
87
|
-
lineHeight: PropTypes.number,
|
|
88
|
-
}),
|
|
75
|
+
labelAnnotation: PropTypes.object,
|
|
89
76
|
showAnnotations: PropTypes.bool,
|
|
90
77
|
controlAnnotation: PropTypes.bool,
|
|
91
78
|
annotationsData: PropTypes.arrayOf(
|
|
@@ -106,7 +93,7 @@ export const LineChartPropTypes = {
|
|
|
106
93
|
}),
|
|
107
94
|
legend: PropTypes.shape({
|
|
108
95
|
display: PropTypes.bool,
|
|
109
|
-
position: PropTypes.oneOf(['top', 'bottom', 'right'
|
|
96
|
+
position: PropTypes.oneOf(['top', 'bottom', 'right']),
|
|
110
97
|
align: PropTypes.oneOf(['start', 'center', 'end']),
|
|
111
98
|
customLegend: PropTypes.shape({
|
|
112
99
|
customLegendPlugin: PropTypes.object,
|
|
@@ -214,24 +201,7 @@ export const getDefaultProps = (props) => {
|
|
|
214
201
|
props.chart.options.graph.showMinorGridlines || false,
|
|
215
202
|
},
|
|
216
203
|
annotations: {
|
|
217
|
-
labelAnnotation: {
|
|
218
|
-
showLabel:
|
|
219
|
-
props.chart.options.annotations.labelAnnotation?.showLabel ?? false,
|
|
220
|
-
text: props.chart.options.annotations.labelAnnotation?.text ?? '',
|
|
221
|
-
position:
|
|
222
|
-
props.chart.options.annotations.labelAnnotation?.position ??
|
|
223
|
-
TextLabelPosition.BOTTOM_RIGHT,
|
|
224
|
-
fontSize:
|
|
225
|
-
props.chart.options.annotations.labelAnnotation?.fontSize ?? 12,
|
|
226
|
-
xOffset:
|
|
227
|
-
props.chart.options.annotations.labelAnnotation?.xOffset ?? 5,
|
|
228
|
-
yOffset:
|
|
229
|
-
props.chart.options.annotations.labelAnnotation?.yOffset ?? 5,
|
|
230
|
-
maxWidth:
|
|
231
|
-
props.chart.options.annotations.labelAnnotation?.maxWidth ?? 300,
|
|
232
|
-
lineHeight:
|
|
233
|
-
props.chart.options.annotations.labelAnnotation?.lineHeight ?? 12,
|
|
234
|
-
},
|
|
204
|
+
labelAnnotation: props.chart.options.annotations.labelAnnotation || {},
|
|
235
205
|
showAnnotations:
|
|
236
206
|
props.chart.options.annotations.showAnnotations ?? false,
|
|
237
207
|
controlAnnotation:
|
|
@@ -29,8 +29,8 @@ import { useChartOptions } from './hooks/use-chart-options';
|
|
|
29
29
|
import { useChartPlugins } from './hooks/use-chart-plugins';
|
|
30
30
|
import { generateKey } from './utils/line-chart-utils';
|
|
31
31
|
import { useChartState } from './state/use-chart-state';
|
|
32
|
-
import {
|
|
33
|
-
import {
|
|
32
|
+
import { getConfig } from './utils/initialize/initialize-line-chart';
|
|
33
|
+
import { INIT_KEYS } from './constants/line-chart-consts';
|
|
34
34
|
|
|
35
35
|
ChartJS.register(
|
|
36
36
|
LinearScale,
|
|
@@ -46,7 +46,6 @@ ChartJS.register(
|
|
|
46
46
|
dataLabelsPlugin,
|
|
47
47
|
annotationPlugin,
|
|
48
48
|
dragDataPlugin,
|
|
49
|
-
chartAreaTextPlugin,
|
|
50
49
|
);
|
|
51
50
|
|
|
52
51
|
/**
|
|
@@ -57,7 +56,7 @@ const LineChart = (props) => {
|
|
|
57
56
|
setDefaultTheme();
|
|
58
57
|
const chartRef = useRef(null);
|
|
59
58
|
const { table, translations: translationsRaw } = props;
|
|
60
|
-
const translations =
|
|
59
|
+
const translations = getConfig(INIT_KEYS.TRANSLATIONS);
|
|
61
60
|
const chart = getDefaultProps(props);
|
|
62
61
|
const {
|
|
63
62
|
data: { datasets },
|
|
@@ -93,14 +92,13 @@ const LineChart = (props) => {
|
|
|
93
92
|
persistenceId,
|
|
94
93
|
});
|
|
95
94
|
|
|
96
|
-
const { resetZoom,
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
});
|
|
95
|
+
const { resetZoom, handleKeyDown, handleKeyUp } = useChartFunctions({
|
|
96
|
+
chartRef,
|
|
97
|
+
state,
|
|
98
|
+
options,
|
|
99
|
+
dispatch,
|
|
100
|
+
generatedDatasets,
|
|
101
|
+
});
|
|
104
102
|
|
|
105
103
|
const useOptions = useChartOptions({
|
|
106
104
|
chartRef,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getTranslations } from '../get-translations/get-translations';
|
|
2
|
+
import { INIT_KEYS } from '../../constants/line-chart-consts';
|
|
3
|
+
|
|
4
|
+
const config = {
|
|
5
|
+
[INIT_KEYS.TRANSLATIONS]: getTranslations(),
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Retrieve the value for the given key from the config object.
|
|
10
|
+
* @param {string} key - The key to access the corresponding value in the config object.
|
|
11
|
+
* @returns {*} - The value associated with the given key in the config object.
|
|
12
|
+
*/
|
|
13
|
+
export const getConfig = (key) => config[key];
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Initialize the charts library with the provided configurations.
|
|
17
|
+
* This function will store the configuration options in a config object.
|
|
18
|
+
* @param {object} options - An object containing the configuration options for the library.
|
|
19
|
+
*/
|
|
20
|
+
export const initializeLineChart = (options = {}) => {
|
|
21
|
+
Object.entries(options).forEach(([key, value]) => {
|
|
22
|
+
if (key === INIT_KEYS.TRANSLATIONS) {
|
|
23
|
+
config[key] = getTranslations(value);
|
|
24
|
+
} else {
|
|
25
|
+
config[key] = { ...value };
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
};
|
|
@@ -26,17 +26,12 @@ export interface IChartAnnotationsData {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export interface ILabelAnnotation {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
xOffset?: number
|
|
34
|
-
yOffset?: number
|
|
35
|
-
maxWidth?: number
|
|
36
|
-
lineHeight?: number
|
|
29
|
+
content: string[];
|
|
30
|
+
fontSize: number;
|
|
31
|
+
xAdjust: number;
|
|
32
|
+
yAdjust: number;
|
|
37
33
|
}
|
|
38
34
|
|
|
39
|
-
|
|
40
35
|
export interface IChartAnnotations {
|
|
41
36
|
showAnnotations: boolean;
|
|
42
37
|
controlAnnotation: boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { round } from '@oliasoft-open-source/units';
|
|
2
2
|
import { defaults } from 'chart.js';
|
|
3
3
|
import cx from 'classnames';
|
|
4
|
-
import { chartMinorGridlinesPlugin } from '../components/line-chart/
|
|
4
|
+
import { chartMinorGridlinesPlugin } from '../components/line-chart/line-chart.minor-gridlines-plugin';
|
|
5
5
|
import {
|
|
6
6
|
BORDER_COLOR,
|
|
7
7
|
CUSTOM_LEGEND_PLUGIN_NAME,
|
|
@@ -86,6 +86,37 @@ const generateAnnotations = (options, state) => {
|
|
|
86
86
|
return annotations;
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* @param {import('../components/bar-chart/bar-chart.interface').IBarChartOptions |
|
|
91
|
+
* import('../components/line-chart/line-chart.interface').ILineChartOptions} options - chart options object
|
|
92
|
+
* @return {{label1: {}}}
|
|
93
|
+
*/
|
|
94
|
+
const getLabelAnnotation = (options) => {
|
|
95
|
+
const { annotations = {} } = options;
|
|
96
|
+
const { labelAnnotation = {} } = annotations;
|
|
97
|
+
const isDarkModeOn = options.chartStyling.darkMode || false;
|
|
98
|
+
const {
|
|
99
|
+
content = [],
|
|
100
|
+
xAdjust = -200,
|
|
101
|
+
yAdjust = 120,
|
|
102
|
+
fontSize = 12,
|
|
103
|
+
} = labelAnnotation;
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
label1: {
|
|
107
|
+
type: 'label',
|
|
108
|
+
xAdjust,
|
|
109
|
+
yAdjust,
|
|
110
|
+
backgroundColor: 'rgba(0, 0, 0, 0)',
|
|
111
|
+
color: isDarkModeOn && 'rgba(255, 255, 255, 1)',
|
|
112
|
+
content,
|
|
113
|
+
font: {
|
|
114
|
+
size: fontSize,
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
};
|
|
119
|
+
|
|
89
120
|
/**
|
|
90
121
|
* @param {import('../components/bar-chart/bar-chart.interface').IBarChartOptions |
|
|
91
122
|
* import('../components/line-chart/line-chart.interface').ILineChartOptions} options - chart options object
|
|
@@ -93,14 +124,20 @@ const generateAnnotations = (options, state) => {
|
|
|
93
124
|
* @return {{annotations: []}}
|
|
94
125
|
*/
|
|
95
126
|
const getAnnotation = (options, state) => {
|
|
96
|
-
const {
|
|
97
|
-
const
|
|
127
|
+
const { annotations } = options;
|
|
128
|
+
const isAnnotationShown = annotations?.showAnnotations;
|
|
129
|
+
const isAnnotationDataProvided = annotations?.annotationsData?.length;
|
|
98
130
|
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
131
|
+
const formAnnotation =
|
|
132
|
+
isAnnotationShown && isAnnotationDataProvided
|
|
133
|
+
? {
|
|
134
|
+
...getLabelAnnotation(options),
|
|
135
|
+
...generateAnnotations(options, state),
|
|
136
|
+
}
|
|
137
|
+
: null;
|
|
102
138
|
|
|
103
|
-
return {
|
|
139
|
+
return {
|
|
140
|
+
annotations: formAnnotation,
|
|
141
|
+
};
|
|
104
142
|
};
|
|
105
|
-
|
|
106
143
|
export default getAnnotation;
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
import { TextLabelPosition } from './plugin-constants';
|
|
2
|
-
import { AlignOptions } from '../../../helpers/enums';
|
|
3
|
-
|
|
4
|
-
const WORD_SEPARATOR = ' ';
|
|
5
|
-
const TRANSPARENT = 'rgba(0, 0, 0, 0.5)';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Splits the input text into words based on the predefined WORD_SEPARATOR.
|
|
9
|
-
* If the input is an array, it first joins the array and then splits it.
|
|
10
|
-
*
|
|
11
|
-
* @param {string | string[]} text - The text to split into words.
|
|
12
|
-
* @returns {string[]} An array of words.
|
|
13
|
-
*/
|
|
14
|
-
const getWords = (text) => {
|
|
15
|
-
return (Array.isArray(text) ? text.join(WORD_SEPARATOR) : text).split(
|
|
16
|
-
WORD_SEPARATOR,
|
|
17
|
-
);
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Counts the number of lines required to render the words within the specified maxWidth.
|
|
22
|
-
* It takes into consideration the context (ctx) provided to calculate the text width.
|
|
23
|
-
*
|
|
24
|
-
* @param {string[]} words - The array of words to be processed.
|
|
25
|
-
* @param {number} maxWidth - The maximum width allowed for the text.
|
|
26
|
-
* @param {CanvasRenderingContext2D} ctx - The canvas rendering context to measure the text width.
|
|
27
|
-
* @returns {number} The number of lines required.
|
|
28
|
-
*/
|
|
29
|
-
const countLines = (words, maxWidth, ctx) => {
|
|
30
|
-
const lineCount = words.reduce(
|
|
31
|
-
(lines, word) => {
|
|
32
|
-
const testLine = `${lines.currentLine}${word}${WORD_SEPARATOR}`;
|
|
33
|
-
const { width: testWidth } = ctx.measureText(testLine);
|
|
34
|
-
|
|
35
|
-
if (testWidth > maxWidth) {
|
|
36
|
-
return {
|
|
37
|
-
lineCount: lines.lineCount + 1,
|
|
38
|
-
currentLine: `${word}${WORD_SEPARATOR}`,
|
|
39
|
-
};
|
|
40
|
-
} else {
|
|
41
|
-
return { lineCount: lines.lineCount, currentLine: testLine };
|
|
42
|
-
}
|
|
43
|
-
},
|
|
44
|
-
{ lineCount: 0, currentLine: '' },
|
|
45
|
-
);
|
|
46
|
-
|
|
47
|
-
return lineCount.lineCount + 1; // Add the last line
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Renders the lines of text on the canvas context.
|
|
52
|
-
* It iterates over the array of lines and renders each line with the provided styling.
|
|
53
|
-
*
|
|
54
|
-
* @param {CanvasRenderingContext2D} ctx - The canvas rendering context to draw on.
|
|
55
|
-
* @param {string[]} lines - The array of lines to be rendered.
|
|
56
|
-
* @param {number} lineHeight - The height of each line.
|
|
57
|
-
* @param {number} x - The x-coordinate of the starting position.
|
|
58
|
-
* @param {number} y - The y-coordinate of the starting position.
|
|
59
|
-
* @param {string} position - The position for the text (one of the values from the TextLabelPosition enum).
|
|
60
|
-
*/
|
|
61
|
-
const drawText = (ctx, lines, lineHeight, x, y, position) => {
|
|
62
|
-
lines.forEach((line, index) => {
|
|
63
|
-
const lineY = position.includes('top')
|
|
64
|
-
? y + lineHeight * (index + 1) - 5
|
|
65
|
-
: y - (lines.length - 1 - index) * lineHeight;
|
|
66
|
-
ctx.fillText(line, x, lineY);
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Calculates the maximum width for the text based on the initial maximum width
|
|
72
|
-
* and the chart area width.
|
|
73
|
-
* @param {number} initialMaxWidth - The initial maximum width.
|
|
74
|
-
* @param {number} chartAreaWidth - The width of the chart area.
|
|
75
|
-
* @returns {number} The updated maximum width.
|
|
76
|
-
*/
|
|
77
|
-
const calculateMaxWidth = (initialMaxWidth, chartAreaWidth) => {
|
|
78
|
-
const factorMiddle = 0.5;
|
|
79
|
-
const factorSmall = 0.7;
|
|
80
|
-
const maxWidthFactor =
|
|
81
|
-
chartAreaWidth < 500
|
|
82
|
-
? factorMiddle
|
|
83
|
-
: chartAreaWidth < 700
|
|
84
|
-
? factorSmall
|
|
85
|
-
: 1;
|
|
86
|
-
return initialMaxWidth * maxWidthFactor;
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Determines the legend dimensions (width and height) based on its position.
|
|
91
|
-
*
|
|
92
|
-
* @param {object} chart - The Chart.js chart object.
|
|
93
|
-
* @returns {object} An object containing the legend width and height.
|
|
94
|
-
*/
|
|
95
|
-
const getLegendDimensions = (chart) => {
|
|
96
|
-
const { legend } = chart;
|
|
97
|
-
|
|
98
|
-
const legendWidth =
|
|
99
|
-
legend && legend.display && legend.options.position === 'left'
|
|
100
|
-
? legend.width + legend.options.labels.padding * 2
|
|
101
|
-
: 0;
|
|
102
|
-
|
|
103
|
-
const legendHeight =
|
|
104
|
-
legend &&
|
|
105
|
-
legend.display &&
|
|
106
|
-
(legend.options.position === 'top' || legend.options.position === 'bottom')
|
|
107
|
-
? legend.height + legend.options.labels.padding * 2
|
|
108
|
-
: 0;
|
|
109
|
-
|
|
110
|
-
return { legendWidth, legendHeight };
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Determines the X and Y coordinates for the provided position.
|
|
115
|
-
*
|
|
116
|
-
* @param {string} position - The position for the text (one of the values from the TextLabelPosition enum).
|
|
117
|
-
* @param {object} chart - The Chart.js chart object.
|
|
118
|
-
* @param {number} xOffset - The horizontal offset from the specified position.
|
|
119
|
-
* @param {number} yOffset - The vertical offset from the specified position.
|
|
120
|
-
* @returns {number[]} An array with the X and Y coordinates.
|
|
121
|
-
*/
|
|
122
|
-
const getPositionCoordinates = (position, chart, xOffset, yOffset) => {
|
|
123
|
-
const { chartArea } = chart;
|
|
124
|
-
|
|
125
|
-
const { legendWidth, legendHeight } = getLegendDimensions(chart);
|
|
126
|
-
|
|
127
|
-
switch (position) {
|
|
128
|
-
case TextLabelPosition.TOP_LEFT:
|
|
129
|
-
return [
|
|
130
|
-
chartArea.left + xOffset + legendWidth,
|
|
131
|
-
chartArea.top + yOffset + legendHeight,
|
|
132
|
-
];
|
|
133
|
-
case TextLabelPosition.TOP_CENTER:
|
|
134
|
-
return [
|
|
135
|
-
chartArea.left + chartArea.width / 2,
|
|
136
|
-
chartArea.top + yOffset + legendHeight,
|
|
137
|
-
];
|
|
138
|
-
case TextLabelPosition.TOP_RIGHT:
|
|
139
|
-
return [
|
|
140
|
-
chartArea.right - xOffset,
|
|
141
|
-
chartArea.top + yOffset + legendHeight,
|
|
142
|
-
];
|
|
143
|
-
case TextLabelPosition.MIDDLE_LEFT:
|
|
144
|
-
return [
|
|
145
|
-
chartArea.left + xOffset + legendWidth,
|
|
146
|
-
chartArea.top + chartArea.height / 2,
|
|
147
|
-
];
|
|
148
|
-
case TextLabelPosition.MIDDLE_CENTER:
|
|
149
|
-
return [
|
|
150
|
-
chartArea.left + chartArea.width / 2,
|
|
151
|
-
chartArea.top + chartArea.height / 2,
|
|
152
|
-
];
|
|
153
|
-
case TextLabelPosition.MIDDLE_RIGHT:
|
|
154
|
-
return [
|
|
155
|
-
chartArea.right - xOffset - legendWidth,
|
|
156
|
-
chartArea.top + chartArea.height / 2,
|
|
157
|
-
];
|
|
158
|
-
case TextLabelPosition.BOTTOM_LEFT:
|
|
159
|
-
return [
|
|
160
|
-
chartArea.left + xOffset + legendWidth,
|
|
161
|
-
chartArea.bottom - yOffset - legendHeight,
|
|
162
|
-
];
|
|
163
|
-
case TextLabelPosition.BOTTOM_CENTER:
|
|
164
|
-
return [
|
|
165
|
-
chartArea.left + chartArea.width / 2,
|
|
166
|
-
chartArea.bottom - yOffset - legendHeight,
|
|
167
|
-
];
|
|
168
|
-
case TextLabelPosition.BOTTOM_RIGHT:
|
|
169
|
-
default:
|
|
170
|
-
return [
|
|
171
|
-
chartArea.right - xOffset - legendWidth,
|
|
172
|
-
chartArea.bottom - yOffset - legendHeight,
|
|
173
|
-
];
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Determines the appropriate text alignment based on the position provided.
|
|
179
|
-
*
|
|
180
|
-
* @param {string} position - The position for the text (one of the values from the TextLabelPosition enum).
|
|
181
|
-
* @returns {string} The text alignment ('left', 'center', or 'right').
|
|
182
|
-
*/
|
|
183
|
-
const getTextAlign = (position) => {
|
|
184
|
-
if (position.includes(AlignOptions.Center)) {
|
|
185
|
-
return AlignOptions.Center;
|
|
186
|
-
} else if (position.includes(AlignOptions.Left)) {
|
|
187
|
-
return AlignOptions.Left;
|
|
188
|
-
} else {
|
|
189
|
-
return AlignOptions.Right;
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
export const chartAreaTextPlugin = {
|
|
194
|
-
id: 'chartAreaText',
|
|
195
|
-
|
|
196
|
-
beforeLayout: (chart, args, options) => {
|
|
197
|
-
const { showLabel, text, fontStyle, fontSize, maxWidth, lineHeight } =
|
|
198
|
-
options;
|
|
199
|
-
const { ctx } = chart;
|
|
200
|
-
|
|
201
|
-
if (!showLabel || !text) return;
|
|
202
|
-
|
|
203
|
-
ctx.save();
|
|
204
|
-
ctx.font = `${fontStyle} ${fontSize}px Arial`;
|
|
205
|
-
|
|
206
|
-
const words = getWords(text);
|
|
207
|
-
const lines = countLines(words, maxWidth, ctx);
|
|
208
|
-
|
|
209
|
-
// Calculate and set the padding needed at the top or bottom of the chart
|
|
210
|
-
const paddingNeeded = lines * lineHeight + lineHeight;
|
|
211
|
-
if (options.position.includes('top')) {
|
|
212
|
-
chart.options.layout.padding.top = paddingNeeded;
|
|
213
|
-
} else {
|
|
214
|
-
chart.options.layout.padding.bottom = paddingNeeded;
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
ctx.restore();
|
|
218
|
-
},
|
|
219
|
-
|
|
220
|
-
beforeDraw: (chart, args, options) => {
|
|
221
|
-
const {
|
|
222
|
-
showLabel,
|
|
223
|
-
text,
|
|
224
|
-
fontSize,
|
|
225
|
-
xOffset,
|
|
226
|
-
yOffset,
|
|
227
|
-
lineHeight,
|
|
228
|
-
maxWidth: initialMaxWidth,
|
|
229
|
-
position,
|
|
230
|
-
} = options;
|
|
231
|
-
const { ctx, chartArea } = chart;
|
|
232
|
-
|
|
233
|
-
if (!showLabel || !text) return;
|
|
234
|
-
|
|
235
|
-
// Determine the maxWidth based on chartArea width
|
|
236
|
-
const maxWidth = calculateMaxWidth(initialMaxWidth, chartArea.width);
|
|
237
|
-
|
|
238
|
-
// Split the text into words and calculate the number of lines
|
|
239
|
-
const words = getWords(text);
|
|
240
|
-
let line = '';
|
|
241
|
-
let lines = [];
|
|
242
|
-
for (let i = 0; i < words.length; i++) {
|
|
243
|
-
const testLine = `${line}${words[i]}${WORD_SEPARATOR}`;
|
|
244
|
-
const { width: testWidth } = ctx.measureText(testLine);
|
|
245
|
-
if (testWidth > maxWidth) {
|
|
246
|
-
lines.push(line.trim());
|
|
247
|
-
line = `${words[i]}${WORD_SEPARATOR}`;
|
|
248
|
-
} else {
|
|
249
|
-
line = testLine;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
lines.push(line.trim()); // Add the last line
|
|
253
|
-
|
|
254
|
-
// Wrap the text based on the maxWidth and draw it on the canvas
|
|
255
|
-
ctx.save();
|
|
256
|
-
ctx.font = `${fontSize}px Arial`;
|
|
257
|
-
ctx.fillStyle = TRANSPARENT;
|
|
258
|
-
ctx.textAlign = AlignOptions.Right;
|
|
259
|
-
|
|
260
|
-
const [x, y] = getPositionCoordinates(position, chart, xOffset, yOffset);
|
|
261
|
-
ctx.textAlign = getTextAlign(position);
|
|
262
|
-
|
|
263
|
-
drawText(ctx, lines, lineHeight, x, y, position);
|
|
264
|
-
|
|
265
|
-
ctx.restore();
|
|
266
|
-
},
|
|
267
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export const TextLabelPosition = {
|
|
2
|
-
TOP_LEFT: 'top-left',
|
|
3
|
-
TOP_CENTER: 'top-center',
|
|
4
|
-
TOP_RIGHT: 'top-right',
|
|
5
|
-
MIDDLE_LEFT: 'middle-left',
|
|
6
|
-
MIDDLE_CENTER: 'middle-center',
|
|
7
|
-
MIDDLE_RIGHT: 'middle-right',
|
|
8
|
-
BOTTOM_LEFT: 'bottom-left',
|
|
9
|
-
BOTTOM_CENTER: 'bottom-center',
|
|
10
|
-
BOTTOM_RIGHT: 'bottom-right',
|
|
11
|
-
};
|