chartjs-plugin-trendline 3.2.0 → 3.2.3
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/.github/copilot-instructions.md +40 -40
- package/.github/workflows/release.yml +64 -61
- package/.github/workflows/tests.yml +26 -26
- package/.prettierrc +5 -5
- package/CLAUDE.md +44 -44
- package/GEMINI.md +40 -40
- package/LICENSE +21 -21
- package/MIGRATION.md +126 -126
- package/README.md +166 -166
- package/babel.config.js +3 -3
- package/changelog.md +39 -39
- package/dist/chartjs-plugin-trendline.cjs +884 -885
- package/dist/chartjs-plugin-trendline.esm.js +882 -883
- package/dist/chartjs-plugin-trendline.js +890 -891
- package/dist/chartjs-plugin-trendline.min.js +8 -8
- package/dist/chartjs-plugin-trendline.min.js.map +1 -1
- package/example/barChart.html +165 -165
- package/example/barChartWithNullValues.html +168 -168
- package/example/barChart_label.html +174 -174
- package/example/exponentialChart.html +244 -244
- package/example/lineChart.html +210 -210
- package/example/lineChartProjection.html +261 -261
- package/example/lineChartTypeTime.html +190 -190
- package/example/scatterChart.html +136 -136
- package/example/scatterProjection.html +141 -141
- package/example/test-null-handling.html +59 -59
- package/index.html +215 -215
- package/jest.config.js +4 -4
- package/package.json +45 -40
- package/rollup.config.js +54 -54
- package/src/components/label.js +56 -56
- package/src/components/label.test.js +129 -129
- package/src/components/trendline.js +375 -375
- package/src/components/trendline.test.js +789 -789
- package/src/core/plugin.js +78 -79
- package/src/core/plugin.test.js +307 -0
- package/src/index.js +12 -12
- package/src/utils/drawing.js +125 -125
- package/src/utils/drawing.test.js +308 -308
- package/src/utils/exponentialFitter.js +146 -146
- package/src/utils/exponentialFitter.test.js +362 -362
- package/src/utils/lineFitter.js +86 -86
- package/src/utils/lineFitter.test.js +340 -340
package/src/utils/drawing.js
CHANGED
|
@@ -1,126 +1,126 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Retrieves the x and y scales from the chart instance.
|
|
3
|
-
* @param {Chart} chartInstance - The chart instance.
|
|
4
|
-
* @returns {Object} - The xScale and yScale of the chart.
|
|
5
|
-
*/
|
|
6
|
-
export const getScales = (chartInstance) => {
|
|
7
|
-
let xScale, yScale;
|
|
8
|
-
for (const scale of Object.values(chartInstance.scales)) {
|
|
9
|
-
if (scale.isHorizontal()) xScale = scale;
|
|
10
|
-
else yScale = scale;
|
|
11
|
-
if (xScale && yScale) break;
|
|
12
|
-
}
|
|
13
|
-
return { xScale, yScale };
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Sets the line style (dashed, dotted, solid) for the canvas context.
|
|
18
|
-
* @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
|
|
19
|
-
* @param {string} lineStyle - The style of the line ('dotted', 'dashed', 'solid', etc.).
|
|
20
|
-
*/
|
|
21
|
-
export const setLineStyle = (ctx, lineStyle) => {
|
|
22
|
-
switch (lineStyle) {
|
|
23
|
-
case 'dotted':
|
|
24
|
-
ctx.setLineDash([2, 2]);
|
|
25
|
-
break;
|
|
26
|
-
case 'dashed':
|
|
27
|
-
ctx.setLineDash([8, 3]);
|
|
28
|
-
break;
|
|
29
|
-
case 'dashdot':
|
|
30
|
-
ctx.setLineDash([8, 3, 2, 3]);
|
|
31
|
-
break;
|
|
32
|
-
case 'solid':
|
|
33
|
-
default:
|
|
34
|
-
ctx.setLineDash([]);
|
|
35
|
-
break;
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Draws the trendline on the canvas context.
|
|
41
|
-
* @param {Object} params - The trendline parameters.
|
|
42
|
-
* @param {CanvasRenderingContext2D} params.ctx - The canvas rendering context.
|
|
43
|
-
* @param {number} params.x1 - Starting x-coordinate of the trendline.
|
|
44
|
-
* @param {number} params.y1 - Starting y-coordinate of the trendline.
|
|
45
|
-
* @param {number} params.x2 - Ending x-coordinate of the trendline.
|
|
46
|
-
* @param {number} params.y2 - Ending y-coordinate of the trendline.
|
|
47
|
-
* @param {string} params.colorMin - The starting color of the trendline gradient.
|
|
48
|
-
* @param {string} params.colorMax - The ending color of the trendline gradient.
|
|
49
|
-
*/
|
|
50
|
-
export const drawTrendline = ({ ctx, x1, y1, x2, y2, colorMin, colorMax }) => {
|
|
51
|
-
// Ensure all values are finite numbers
|
|
52
|
-
if (!isFinite(x1) || !isFinite(y1) || !isFinite(x2) || !isFinite(y2)) {
|
|
53
|
-
console.warn(
|
|
54
|
-
'Cannot draw trendline: coordinates contain non-finite values',
|
|
55
|
-
{ x1, y1, x2, y2 }
|
|
56
|
-
);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
ctx.beginPath();
|
|
61
|
-
ctx.moveTo(x1, y1);
|
|
62
|
-
ctx.lineTo(x2, y2);
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
// Additional validation for degenerate gradients
|
|
66
|
-
const dx = x2 - x1;
|
|
67
|
-
const dy = y2 - y1;
|
|
68
|
-
const gradientLength = Math.sqrt(dx * dx + dy * dy);
|
|
69
|
-
|
|
70
|
-
// If the gradient vector is too small, createLinearGradient may fail
|
|
71
|
-
if (gradientLength < 0.01) {
|
|
72
|
-
console.warn('Gradient vector too small, using solid color:', { x1, y1, x2, y2, length: gradientLength });
|
|
73
|
-
ctx.strokeStyle = colorMin;
|
|
74
|
-
} else {
|
|
75
|
-
let gradient = ctx.createLinearGradient(x1, y1, x2, y2);
|
|
76
|
-
gradient.addColorStop(0, colorMin);
|
|
77
|
-
gradient.addColorStop(1, colorMax);
|
|
78
|
-
ctx.strokeStyle = gradient;
|
|
79
|
-
}
|
|
80
|
-
} catch (e) {
|
|
81
|
-
// Fallback to solid color if gradient creation fails
|
|
82
|
-
console.warn('Gradient creation failed, using solid color:', e);
|
|
83
|
-
ctx.strokeStyle = colorMin;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
ctx.stroke();
|
|
87
|
-
ctx.closePath();
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Fills the area below the trendline with the specified color.
|
|
92
|
-
* @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
|
|
93
|
-
* @param {number} x1 - Starting x-coordinate of the trendline.
|
|
94
|
-
* @param {number} y1 - Starting y-coordinate of the trendline.
|
|
95
|
-
* @param {number} x2 - Ending x-coordinate of the trendline.
|
|
96
|
-
* @param {number} y2 - Ending y-coordinate of the trendline.
|
|
97
|
-
* @param {number} drawBottom - The bottom boundary of the chart.
|
|
98
|
-
* @param {string} fillColor - The color to fill below the trendline.
|
|
99
|
-
*/
|
|
100
|
-
export const fillBelowTrendline = (ctx, x1, y1, x2, y2, drawBottom, fillColor) => {
|
|
101
|
-
// Ensure all values are finite numbers
|
|
102
|
-
if (
|
|
103
|
-
!isFinite(x1) ||
|
|
104
|
-
!isFinite(y1) ||
|
|
105
|
-
!isFinite(x2) ||
|
|
106
|
-
!isFinite(y2) ||
|
|
107
|
-
!isFinite(drawBottom)
|
|
108
|
-
) {
|
|
109
|
-
console.warn(
|
|
110
|
-
'Cannot fill below trendline: coordinates contain non-finite values',
|
|
111
|
-
{ x1, y1, x2, y2, drawBottom }
|
|
112
|
-
);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
ctx.beginPath();
|
|
117
|
-
ctx.moveTo(x1, y1);
|
|
118
|
-
ctx.lineTo(x2, y2);
|
|
119
|
-
ctx.lineTo(x2, drawBottom);
|
|
120
|
-
ctx.lineTo(x1, drawBottom);
|
|
121
|
-
ctx.lineTo(x1, y1);
|
|
122
|
-
ctx.closePath();
|
|
123
|
-
|
|
124
|
-
ctx.fillStyle = fillColor;
|
|
125
|
-
ctx.fill();
|
|
1
|
+
/**
|
|
2
|
+
* Retrieves the x and y scales from the chart instance.
|
|
3
|
+
* @param {Chart} chartInstance - The chart instance.
|
|
4
|
+
* @returns {Object} - The xScale and yScale of the chart.
|
|
5
|
+
*/
|
|
6
|
+
export const getScales = (chartInstance) => {
|
|
7
|
+
let xScale, yScale;
|
|
8
|
+
for (const scale of Object.values(chartInstance.scales)) {
|
|
9
|
+
if (scale.isHorizontal()) xScale = scale;
|
|
10
|
+
else yScale = scale;
|
|
11
|
+
if (xScale && yScale) break;
|
|
12
|
+
}
|
|
13
|
+
return { xScale, yScale };
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Sets the line style (dashed, dotted, solid) for the canvas context.
|
|
18
|
+
* @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
|
|
19
|
+
* @param {string} lineStyle - The style of the line ('dotted', 'dashed', 'solid', etc.).
|
|
20
|
+
*/
|
|
21
|
+
export const setLineStyle = (ctx, lineStyle) => {
|
|
22
|
+
switch (lineStyle) {
|
|
23
|
+
case 'dotted':
|
|
24
|
+
ctx.setLineDash([2, 2]);
|
|
25
|
+
break;
|
|
26
|
+
case 'dashed':
|
|
27
|
+
ctx.setLineDash([8, 3]);
|
|
28
|
+
break;
|
|
29
|
+
case 'dashdot':
|
|
30
|
+
ctx.setLineDash([8, 3, 2, 3]);
|
|
31
|
+
break;
|
|
32
|
+
case 'solid':
|
|
33
|
+
default:
|
|
34
|
+
ctx.setLineDash([]);
|
|
35
|
+
break;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Draws the trendline on the canvas context.
|
|
41
|
+
* @param {Object} params - The trendline parameters.
|
|
42
|
+
* @param {CanvasRenderingContext2D} params.ctx - The canvas rendering context.
|
|
43
|
+
* @param {number} params.x1 - Starting x-coordinate of the trendline.
|
|
44
|
+
* @param {number} params.y1 - Starting y-coordinate of the trendline.
|
|
45
|
+
* @param {number} params.x2 - Ending x-coordinate of the trendline.
|
|
46
|
+
* @param {number} params.y2 - Ending y-coordinate of the trendline.
|
|
47
|
+
* @param {string} params.colorMin - The starting color of the trendline gradient.
|
|
48
|
+
* @param {string} params.colorMax - The ending color of the trendline gradient.
|
|
49
|
+
*/
|
|
50
|
+
export const drawTrendline = ({ ctx, x1, y1, x2, y2, colorMin, colorMax }) => {
|
|
51
|
+
// Ensure all values are finite numbers
|
|
52
|
+
if (!isFinite(x1) || !isFinite(y1) || !isFinite(x2) || !isFinite(y2)) {
|
|
53
|
+
console.warn(
|
|
54
|
+
'Cannot draw trendline: coordinates contain non-finite values',
|
|
55
|
+
{ x1, y1, x2, y2 }
|
|
56
|
+
);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
ctx.beginPath();
|
|
61
|
+
ctx.moveTo(x1, y1);
|
|
62
|
+
ctx.lineTo(x2, y2);
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
// Additional validation for degenerate gradients
|
|
66
|
+
const dx = x2 - x1;
|
|
67
|
+
const dy = y2 - y1;
|
|
68
|
+
const gradientLength = Math.sqrt(dx * dx + dy * dy);
|
|
69
|
+
|
|
70
|
+
// If the gradient vector is too small, createLinearGradient may fail
|
|
71
|
+
if (gradientLength < 0.01) {
|
|
72
|
+
console.warn('Gradient vector too small, using solid color:', { x1, y1, x2, y2, length: gradientLength });
|
|
73
|
+
ctx.strokeStyle = colorMin;
|
|
74
|
+
} else {
|
|
75
|
+
let gradient = ctx.createLinearGradient(x1, y1, x2, y2);
|
|
76
|
+
gradient.addColorStop(0, colorMin);
|
|
77
|
+
gradient.addColorStop(1, colorMax);
|
|
78
|
+
ctx.strokeStyle = gradient;
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// Fallback to solid color if gradient creation fails
|
|
82
|
+
console.warn('Gradient creation failed, using solid color:', e);
|
|
83
|
+
ctx.strokeStyle = colorMin;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
ctx.stroke();
|
|
87
|
+
ctx.closePath();
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Fills the area below the trendline with the specified color.
|
|
92
|
+
* @param {CanvasRenderingContext2D} ctx - The canvas rendering context.
|
|
93
|
+
* @param {number} x1 - Starting x-coordinate of the trendline.
|
|
94
|
+
* @param {number} y1 - Starting y-coordinate of the trendline.
|
|
95
|
+
* @param {number} x2 - Ending x-coordinate of the trendline.
|
|
96
|
+
* @param {number} y2 - Ending y-coordinate of the trendline.
|
|
97
|
+
* @param {number} drawBottom - The bottom boundary of the chart.
|
|
98
|
+
* @param {string} fillColor - The color to fill below the trendline.
|
|
99
|
+
*/
|
|
100
|
+
export const fillBelowTrendline = (ctx, x1, y1, x2, y2, drawBottom, fillColor) => {
|
|
101
|
+
// Ensure all values are finite numbers
|
|
102
|
+
if (
|
|
103
|
+
!isFinite(x1) ||
|
|
104
|
+
!isFinite(y1) ||
|
|
105
|
+
!isFinite(x2) ||
|
|
106
|
+
!isFinite(y2) ||
|
|
107
|
+
!isFinite(drawBottom)
|
|
108
|
+
) {
|
|
109
|
+
console.warn(
|
|
110
|
+
'Cannot fill below trendline: coordinates contain non-finite values',
|
|
111
|
+
{ x1, y1, x2, y2, drawBottom }
|
|
112
|
+
);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
ctx.beginPath();
|
|
117
|
+
ctx.moveTo(x1, y1);
|
|
118
|
+
ctx.lineTo(x2, y2);
|
|
119
|
+
ctx.lineTo(x2, drawBottom);
|
|
120
|
+
ctx.lineTo(x1, drawBottom);
|
|
121
|
+
ctx.lineTo(x1, y1);
|
|
122
|
+
ctx.closePath();
|
|
123
|
+
|
|
124
|
+
ctx.fillStyle = fillColor;
|
|
125
|
+
ctx.fill();
|
|
126
126
|
};
|