chartjs-plugin-trendline 2.0.5 → 2.1.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 +4 -2
- package/dist/chartjs-plugin-trendline.min.js +1 -1
- package/dist/chartjs-plugin-trendline.min.js.LICENSE.txt +2 -2
- package/example/barChart.html +1 -1
- package/example/barChartWithNullValues.html +1 -1
- package/example/lineChart.html +73 -0
- package/example/lineChartProjection.html +1 -1
- package/package.json +1 -1
- package/src/chartjs-plugin-trendline.js +82 -76
- package/example/lineChart-blood-sugar.html +0 -72
- package/example/lineChart-double.html +0 -111
- package/example/lineChart-time-scale.html +0 -67
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# chartjs-plugin-trendline
|
|
2
2
|
|
|
3
3
|
This plugin draws an linear trendline in your Chart.
|
|
4
|
-
It has been tested with Chart.js version 4.
|
|
4
|
+
It has been tested with Chart.js version 4.4.0.
|
|
5
5
|
|
|
6
6
|
## Installation
|
|
7
7
|
|
|
@@ -10,7 +10,7 @@ It has been tested with Chart.js version 4.3.0.
|
|
|
10
10
|
Load Chart.js first, then the plugin which will automatically register itself with Chart.js
|
|
11
11
|
|
|
12
12
|
```html
|
|
13
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.
|
|
13
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.min.js"></script>
|
|
14
14
|
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-trendline"></script>
|
|
15
15
|
```
|
|
16
16
|
|
|
@@ -38,6 +38,8 @@ To configure the trendline plugin you simply add a new config options to your da
|
|
|
38
38
|
colorMax: "green",
|
|
39
39
|
lineStyle: "dotted|solid",
|
|
40
40
|
width: 2,
|
|
41
|
+
xAxisKey: "time" (optional),
|
|
42
|
+
yAxisKey: "usage" (optional),
|
|
41
43
|
projection: true|false (optional)
|
|
42
44
|
}
|
|
43
45
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/*! For license information please see chartjs-plugin-trendline.min.js.LICENSE.txt */
|
|
2
|
-
(()=>{var t={460:(t,
|
|
2
|
+
(()=>{var t={460:(t,e)=>{const s={id:"chartjs-plugin-trendline",afterDatasetsDraw:t=>{let e,s;for(let i in t.scales)if("x"==i[0]?s=t.scales[i]:e=t.scales[i],s&&e)break;const a=t.ctx;t.data.datasets.forEach(((e,o)=>{const r=e.alwaysShowTrendline||t.isDatasetVisible(o);if(e.trendlineLinear&&r&&e.data.length>1){const r=t.getDatasetMeta(o);i(r,a,e,s,t.scales[r.yAxisID])}})),a.setLineDash([])}},i=(t,e,s,i,o)=>{let r=s.borderColor||"rgba(169,169,169, .6)",n=s.trendlineLinear.colorMin||r,l=s.trendlineLinear.colorMax||r,h=s.trendlineLinear.width||s.borderWidth,d=s.trendlineLinear.lineStyle||"solid",u=s.trendlineLinear.fillColor;const m="object"==typeof t.controller.chart.options.parsing?t.controller.chart.options.parsing:void 0,x=s.trendlineLinear.xAxisKey||m?m.xAxisKey:"x",c=s.trendlineLinear.yAxisKey||m?m.yAxisKey:"y";h=void 0!==h?h:3;let f=new a,X=s.data.findIndex((t=>null!=t)),p=s.data.length-1,y=t.data[X][x],g=t.data[p][x],w="object"==typeof s.data[X];s.data.forEach(((t,e)=>{if(null!=t)if(["time","timeseries"].includes(i.options.type)){let s=null!=t[x]?t[x]:t.t;void 0!==s?f.add(new Date(s).getTime(),t[c]):f.add(e,t)}else w?isNaN(t.x)||isNaN(t.y)?isNaN(t.x)?isNaN(t.y)||f.add(e,t.y):f.add(e,t.x):f.add(t.x,t.y):f.add(e,t)}));let Y,L,P=i.getPixelForValue(f.minx),b=o.getPixelForValue(f.f(f.minx));if(s.trendlineLinear.projection&&f.scale()<0){let t=f.fo();t<f.minx&&(t=f.maxx),Y=i.getPixelForValue(t),L=o.getPixelForValue(f.f(t))}else Y=i.getPixelForValue(f.maxx),L=o.getPixelForValue(f.f(f.maxx));w||(P=y,Y=g);let C=t.controller.chart.chartArea.bottom,v=t.controller.chart.width;if(b>C){let t=b-C,e=b-L;b=C,P+=v*(t/e)}else if(L>C){let t=L-C,e=L-b;L=C,Y=v-(Y-(v-v*(t/e)))}e.lineWidth=h,"dotted"===d?e.setLineDash([2,3]):e.setLineDash([]),e.beginPath(),e.moveTo(P,b),e.lineTo(Y,L);let D=e.createLinearGradient(P,b,Y,L);L<b?(D.addColorStop(0,l),D.addColorStop(1,n)):(D.addColorStop(0,n),D.addColorStop(1,l)),e.strokeStyle=D,e.stroke(),e.closePath(),u&&(e.fillStyle=u,e.beginPath(),e.moveTo(P,b),e.lineTo(Y,L),e.lineTo(Y,C),e.lineTo(P,C),e.closePath(),e.fill())};class a{constructor(){this.count=0,this.sumX=0,this.sumX2=0,this.sumXY=0,this.sumY=0,this.minx=1e100,this.maxx=-1e100,this.maxy=-1e100}add(t,e){t=parseFloat(t),e=parseFloat(e),this.count++,this.sumX+=t,this.sumX2+=t*t,this.sumXY+=t*e,this.sumY+=e,t<this.minx&&(this.minx=t),t>this.maxx&&(this.maxx=t),e>this.maxy&&(this.maxy=e)}f(t){t=parseFloat(t);let e=this.count*this.sumX2-this.sumX*this.sumX;return(this.sumX2*this.sumY-this.sumX*this.sumXY)/e+t*((this.count*this.sumXY-this.sumX*this.sumY)/e)}fo(){let t=this.count*this.sumX2-this.sumX*this.sumX;return-(this.sumX2*this.sumY-this.sumX*this.sumXY)/t/((this.count*this.sumXY-this.sumX*this.sumY)/t)}scale(){let t=this.count*this.sumX2-this.sumX*this.sumX;return(this.count*this.sumXY-this.sumX*this.sumY)/t}}"undefined"!=typeof window&&window.Chart&&(window.Chart.hasOwnProperty("register")?window.Chart.register(s):window.Chart.plugins.register(s));try{t.exports=s}catch(t){}}},e={};!function s(i){var a=e[i];if(void 0!==a)return a.exports;var o=e[i]={exports:{}};return t[i](o,o.exports,s),o.exports}(460)})();
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* chartjs-plugin-trendline.js
|
|
3
|
-
* Version: 2.0
|
|
3
|
+
* Version: 2.1.0
|
|
4
4
|
*
|
|
5
|
-
* Copyright
|
|
5
|
+
* Copyright 2024 Marcus Alsterfjord
|
|
6
6
|
* Released under the MIT license
|
|
7
7
|
* https://github.com/Makanz/chartjs-plugin-trendline/blob/master/README.md
|
|
8
8
|
*
|
package/example/barChart.html
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
7
7
|
<title>BarChart Example</title>
|
|
8
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js"></script>
|
|
9
9
|
<script src="./../src/chartjs-plugin-trendline.js"></script>
|
|
10
10
|
<script>
|
|
11
11
|
document.addEventListener("DOMContentLoaded", function(event) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
7
7
|
<title>BarChart Example</title>
|
|
8
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js"></script>
|
|
9
9
|
<script src="./../src/chartjs-plugin-trendline.js"></script>
|
|
10
10
|
<script>
|
|
11
11
|
document.addEventListener("DOMContentLoaded", function(event) {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
7
|
+
<title>LineChart Example</title>
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js"></script>
|
|
9
|
+
<script src="./../src/chartjs-plugin-trendline.js"></script>
|
|
10
|
+
<script>
|
|
11
|
+
document.addEventListener("DOMContentLoaded", function(event) {
|
|
12
|
+
new Chart(document.getElementById("line-chart"), {
|
|
13
|
+
type: 'line',
|
|
14
|
+
data: {
|
|
15
|
+
labels: [1500,1600,1700,1750,1800,1850,1900,1950,1999,2050],
|
|
16
|
+
datasets: [{
|
|
17
|
+
data: [86,114,106,106,107,111,133,221,783,2478],
|
|
18
|
+
label: "Africa",
|
|
19
|
+
borderColor: "#3e95cd",
|
|
20
|
+
fill: false,
|
|
21
|
+
trendlineLinear: {
|
|
22
|
+
colorMin: "#3e95cd",
|
|
23
|
+
lineStyle: "line",
|
|
24
|
+
width: 1
|
|
25
|
+
}
|
|
26
|
+
}, {
|
|
27
|
+
data: [282,350,411,502,635,809,947,1402,3700,5267],
|
|
28
|
+
label: "Asia",
|
|
29
|
+
borderColor: "#8e5ea2",
|
|
30
|
+
fill: false,
|
|
31
|
+
trendlineLinear: {
|
|
32
|
+
colorMin: "red",
|
|
33
|
+
colorMax: "green",
|
|
34
|
+
lineStyle: "line",
|
|
35
|
+
width: 1
|
|
36
|
+
}
|
|
37
|
+
}, {
|
|
38
|
+
data: [168,170,178,190,203,276,408,547,675,734],
|
|
39
|
+
label: "Europe",
|
|
40
|
+
borderColor: "#3cba9f",
|
|
41
|
+
fill: false
|
|
42
|
+
}, {
|
|
43
|
+
data: [40,20,10,16,24,38,74,167,508,784],
|
|
44
|
+
label: "Latin America",
|
|
45
|
+
borderColor: "#e8c3b9",
|
|
46
|
+
fill: false
|
|
47
|
+
}, {
|
|
48
|
+
data: [6,3,2,2,7,26,82,172,312,433],
|
|
49
|
+
label: "North America",
|
|
50
|
+
borderColor: "#c45850",
|
|
51
|
+
fill: false
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
},
|
|
55
|
+
options: {
|
|
56
|
+
title: {
|
|
57
|
+
display: true,
|
|
58
|
+
text: 'World population per region (in millions)'
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
</script>
|
|
64
|
+
</head>
|
|
65
|
+
<body>
|
|
66
|
+
<h1>Line Chart</h1>
|
|
67
|
+
|
|
68
|
+
<div style="width: 800px;">
|
|
69
|
+
<canvas id="line-chart"></canvas>
|
|
70
|
+
</div>
|
|
71
|
+
|
|
72
|
+
</body>
|
|
73
|
+
</html>
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
7
7
|
<title>XYlineChart Projection Example</title>
|
|
8
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.
|
|
8
|
+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.js"></script>
|
|
9
9
|
<script src="./../src/chartjs-plugin-trendline.js"></script>
|
|
10
10
|
<script>
|
|
11
11
|
document.addEventListener("DOMContentLoaded", function(event) {
|
package/package.json
CHANGED
|
@@ -1,37 +1,36 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* chartjs-plugin-trendline.js
|
|
3
|
-
* Version: 2.0
|
|
3
|
+
* Version: 2.1.0
|
|
4
4
|
*
|
|
5
|
-
* Copyright
|
|
5
|
+
* Copyright 2024 Marcus Alsterfjord
|
|
6
6
|
* Released under the MIT license
|
|
7
7
|
* https://github.com/Makanz/chartjs-plugin-trendline/blob/master/README.md
|
|
8
8
|
*
|
|
9
9
|
* Mod by: vesal: accept also xy-data so works with scatter
|
|
10
10
|
*/
|
|
11
|
-
|
|
11
|
+
const pluginTrendlineLinear = {
|
|
12
12
|
id: 'chartjs-plugin-trendline',
|
|
13
|
-
afterDatasetsDraw:
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
for (
|
|
13
|
+
afterDatasetsDraw: (chartInstance) => {
|
|
14
|
+
let yScale;
|
|
15
|
+
let xScale;
|
|
16
|
+
for (let axis in chartInstance.scales) {
|
|
17
17
|
if (axis[0] == 'x') xScale = chartInstance.scales[axis];
|
|
18
18
|
else yScale = chartInstance.scales[axis];
|
|
19
19
|
if (xScale && yScale) break;
|
|
20
20
|
}
|
|
21
|
-
|
|
21
|
+
const ctx = chartInstance.ctx;
|
|
22
22
|
|
|
23
|
-
chartInstance.data.datasets.forEach(
|
|
24
|
-
|
|
23
|
+
chartInstance.data.datasets.forEach((dataset, index) => {
|
|
24
|
+
const showTrendline =
|
|
25
25
|
dataset.alwaysShowTrendline ||
|
|
26
26
|
chartInstance.isDatasetVisible(index);
|
|
27
27
|
|
|
28
|
-
// TODO: Add support for objects
|
|
29
28
|
if (
|
|
30
29
|
dataset.trendlineLinear &&
|
|
31
30
|
showTrendline &&
|
|
32
31
|
dataset.data.length > 1
|
|
33
32
|
) {
|
|
34
|
-
|
|
33
|
+
const datasetMeta = chartInstance.getDatasetMeta(index);
|
|
35
34
|
addFitter(
|
|
36
35
|
datasetMeta,
|
|
37
36
|
ctx,
|
|
@@ -46,33 +45,37 @@ var pluginTrendlineLinear = {
|
|
|
46
45
|
},
|
|
47
46
|
};
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
48
|
+
const addFitter = (datasetMeta, ctx, dataset, xScale, yScale) => {
|
|
49
|
+
let defaultColor = dataset.borderColor || 'rgba(169,169,169, .6)';
|
|
50
|
+
let colorMin = dataset.trendlineLinear.colorMin || defaultColor;
|
|
51
|
+
let colorMax = dataset.trendlineLinear.colorMax || defaultColor;
|
|
52
|
+
let lineWidth = dataset.trendlineLinear.width || dataset.borderWidth;
|
|
53
|
+
let lineStyle = dataset.trendlineLinear.lineStyle || 'solid';
|
|
54
|
+
let fillColor = dataset.trendlineLinear.fillColor;
|
|
55
|
+
|
|
56
|
+
const parsing = typeof datasetMeta.controller.chart.options.parsing === "object" ?
|
|
57
|
+
datasetMeta.controller.chart.options.parsing : undefined;
|
|
58
|
+
const xAxisKey = dataset.trendlineLinear.xAxisKey || parsing ? parsing.xAxisKey : "x";
|
|
59
|
+
const yAxisKey = dataset.trendlineLinear.yAxisKey || parsing ? parsing.yAxisKey : "y";
|
|
56
60
|
|
|
57
61
|
lineWidth = lineWidth !== undefined ? lineWidth : 3;
|
|
58
62
|
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
let fitter = new LineFitter();
|
|
64
|
+
let firstIndex = dataset.data.findIndex((d) => {
|
|
61
65
|
return d !== undefined && d !== null;
|
|
62
66
|
});
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
let lastIndex = dataset.data.length - 1;
|
|
68
|
+
let startPos = datasetMeta.data[firstIndex][xAxisKey];
|
|
69
|
+
let endPos = datasetMeta.data[lastIndex][xAxisKey];
|
|
70
|
+
let xy = typeof dataset.data[firstIndex] === 'object';
|
|
67
71
|
|
|
68
|
-
dataset.data.forEach(
|
|
69
|
-
console.log('forEach');
|
|
72
|
+
dataset.data.forEach((data, index) => {
|
|
70
73
|
if (data == null) return;
|
|
71
74
|
|
|
72
75
|
if (['time', 'timeseries'].includes(xScale.options.type)) {
|
|
73
|
-
|
|
76
|
+
let x = data[xAxisKey] != null ? data[xAxisKey] : data.t;
|
|
74
77
|
if (x !== undefined) {
|
|
75
|
-
fitter.add(new Date(x).getTime(), data
|
|
78
|
+
fitter.add(new Date(x).getTime(), data[yAxisKey]);
|
|
76
79
|
} else {
|
|
77
80
|
fitter.add(index, data);
|
|
78
81
|
}
|
|
@@ -89,16 +92,16 @@ function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
|
|
|
89
92
|
}
|
|
90
93
|
});
|
|
91
94
|
|
|
92
|
-
|
|
93
|
-
|
|
95
|
+
let x1 = xScale.getPixelForValue(fitter.minx);
|
|
96
|
+
let y1 = yScale.getPixelForValue(fitter.f(fitter.minx));
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
let x2;
|
|
99
|
+
let y2;
|
|
97
100
|
|
|
98
101
|
// Project only on x axes, do not project if trendline will never hit x axes
|
|
99
102
|
if (dataset.trendlineLinear.projection && fitter.scale() < 0) {
|
|
100
103
|
// X
|
|
101
|
-
|
|
104
|
+
let x2value = fitter.fo();
|
|
102
105
|
if (x2value < fitter.minx) x2value = fitter.maxx;
|
|
103
106
|
x2 = xScale.getPixelForValue(x2value);
|
|
104
107
|
|
|
@@ -114,24 +117,24 @@ function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
|
|
|
114
117
|
x2 = endPos;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
let drawBottom = datasetMeta.controller.chart.chartArea.bottom;
|
|
121
|
+
let chartWidth = datasetMeta.controller.chart.width;
|
|
119
122
|
|
|
120
123
|
if (y1 > drawBottom) {
|
|
121
124
|
// Left side is below zero
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
125
|
+
let diff = y1 - drawBottom;
|
|
126
|
+
let lineHeight = y1 - y2;
|
|
127
|
+
let overlapPercentage = diff / lineHeight;
|
|
128
|
+
let addition = chartWidth * overlapPercentage;
|
|
126
129
|
|
|
127
130
|
y1 = drawBottom;
|
|
128
131
|
x1 = x1 + addition;
|
|
129
132
|
} else if (y2 > drawBottom) {
|
|
130
133
|
// right side is below zero
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
134
|
+
let diff = y2 - drawBottom;
|
|
135
|
+
let lineHeight = y2 - y1;
|
|
136
|
+
let overlapPercentage = diff / lineHeight;
|
|
137
|
+
let subtraction = chartWidth - chartWidth * overlapPercentage;
|
|
135
138
|
|
|
136
139
|
y2 = drawBottom;
|
|
137
140
|
x2 = chartWidth - (x2 - subtraction);
|
|
@@ -149,7 +152,7 @@ function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
|
|
|
149
152
|
ctx.moveTo(x1, y1);
|
|
150
153
|
ctx.lineTo(x2, y2);
|
|
151
154
|
|
|
152
|
-
|
|
155
|
+
let gradient = ctx.createLinearGradient(x1, y1, x2, y2);
|
|
153
156
|
if (y2 < y1) {
|
|
154
157
|
gradient.addColorStop(0, colorMax);
|
|
155
158
|
gradient.addColorStop(1, colorMin);
|
|
@@ -173,21 +176,21 @@ function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
|
|
|
173
176
|
ctx.closePath();
|
|
174
177
|
ctx.fill();
|
|
175
178
|
}
|
|
176
|
-
}
|
|
179
|
+
};
|
|
177
180
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
181
|
+
class LineFitter {
|
|
182
|
+
constructor() {
|
|
183
|
+
this.count = 0;
|
|
184
|
+
this.sumX = 0;
|
|
185
|
+
this.sumX2 = 0;
|
|
186
|
+
this.sumXY = 0;
|
|
187
|
+
this.sumY = 0;
|
|
188
|
+
this.minx = 1e100;
|
|
189
|
+
this.maxx = -1e100;
|
|
190
|
+
this.maxy = -1e100;
|
|
191
|
+
}
|
|
188
192
|
|
|
189
|
-
|
|
190
|
-
add: function (x, y) {
|
|
193
|
+
add(x, y) {
|
|
191
194
|
x = parseFloat(x);
|
|
192
195
|
y = parseFloat(y);
|
|
193
196
|
|
|
@@ -199,31 +202,34 @@ LineFitter.prototype = {
|
|
|
199
202
|
if (x < this.minx) this.minx = x;
|
|
200
203
|
if (x > this.maxx) this.maxx = x;
|
|
201
204
|
if (y > this.maxy) this.maxy = y;
|
|
202
|
-
}
|
|
203
|
-
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
f(x) {
|
|
204
208
|
x = parseFloat(x);
|
|
205
209
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
210
|
+
let det = this.count * this.sumX2 - this.sumX * this.sumX;
|
|
211
|
+
let offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
|
|
212
|
+
let scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
|
|
209
213
|
return offset + x * scale;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
fo() {
|
|
217
|
+
let det = this.count * this.sumX2 - this.sumX * this.sumX;
|
|
218
|
+
let offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
|
|
219
|
+
let scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
|
|
215
220
|
|
|
216
|
-
//
|
|
217
|
-
|
|
221
|
+
// Get x when y = 0
|
|
222
|
+
let xo = -offset / scale;
|
|
218
223
|
return xo;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
scale() {
|
|
227
|
+
let det = this.count * this.sumX2 - this.sumX * this.sumX;
|
|
228
|
+
let scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
|
|
223
229
|
|
|
224
230
|
return scale;
|
|
225
|
-
}
|
|
226
|
-
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
227
233
|
|
|
228
234
|
// If we're in the browser and have access to the global Chart obj, register plugin automatically
|
|
229
235
|
if (typeof window !== 'undefined' && window.Chart) {
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
<html>
|
|
2
|
-
|
|
3
|
-
<head>
|
|
4
|
-
<title>Time scale chart.js</title>
|
|
5
|
-
</head>
|
|
6
|
-
<style>
|
|
7
|
-
.chartBox {
|
|
8
|
-
width: 700px
|
|
9
|
-
}
|
|
10
|
-
</style>
|
|
11
|
-
|
|
12
|
-
<body>
|
|
13
|
-
<div class="chartBox">
|
|
14
|
-
<canvas id="myChart"></canvas>
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
18
|
-
|
|
19
|
-
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
|
|
20
|
-
|
|
21
|
-
<script src="./../src/chartjs-plugin-trendline.js"></script>
|
|
22
|
-
|
|
23
|
-
<script>
|
|
24
|
-
const data = {
|
|
25
|
-
"labels": [
|
|
26
|
-
"2023-08-10 20:00:00",
|
|
27
|
-
"2023-08-10 21:30:00",
|
|
28
|
-
"2023-08-10 22:30:30",
|
|
29
|
-
"2023-08-11 07:00:00",
|
|
30
|
-
"2023-08-11 07:15:00",
|
|
31
|
-
"2023-08-11 08:00:00"
|
|
32
|
-
],
|
|
33
|
-
"datasets": [
|
|
34
|
-
{
|
|
35
|
-
"type": "line",
|
|
36
|
-
"label": "Blood Sugar",
|
|
37
|
-
"data": {
|
|
38
|
-
"2023-08-10 21:30:00": "6.20",
|
|
39
|
-
"2023-08-10 22:30:30": "6.60",
|
|
40
|
-
"2023-08-11 07:00:00": "5.90",
|
|
41
|
-
"2023-08-11 08:00:00": "4.60",
|
|
42
|
-
"2023-08-11 11:17:00": "5.10",
|
|
43
|
-
"2023-08-11 12:15:00": "4.90"
|
|
44
|
-
},
|
|
45
|
-
"backgroundColor": "#A9CCE3",
|
|
46
|
-
"pointStyle": "circle",
|
|
47
|
-
"pointRadius": 6,
|
|
48
|
-
"pointHoverRadius": 12,
|
|
49
|
-
"borderColor": "#5DADE2",
|
|
50
|
-
"trendlineLinear": {
|
|
51
|
-
"colorMin": "red",
|
|
52
|
-
"colorMax": "green",
|
|
53
|
-
"lineStyle": "dotted",
|
|
54
|
-
"width": 3,
|
|
55
|
-
"projection": true
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
],
|
|
59
|
-
};
|
|
60
|
-
const config = {
|
|
61
|
-
type: 'line',
|
|
62
|
-
data
|
|
63
|
-
};
|
|
64
|
-
console.log("Loaded");
|
|
65
|
-
const myChart = new Chart(
|
|
66
|
-
document.getElementById('myChart'),
|
|
67
|
-
config,
|
|
68
|
-
);
|
|
69
|
-
</script>
|
|
70
|
-
</body>
|
|
71
|
-
|
|
72
|
-
</html>
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
|
7
|
-
<title>LineChart Example</title>
|
|
8
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.3.0/dist/chart.umd.js"></script>
|
|
9
|
-
<script src="./../src/chartjs-plugin-trendline.js"></script>
|
|
10
|
-
<script>
|
|
11
|
-
let data = {
|
|
12
|
-
"labels": [
|
|
13
|
-
202303,
|
|
14
|
-
202304,
|
|
15
|
-
202305,
|
|
16
|
-
202306,
|
|
17
|
-
202307,
|
|
18
|
-
202308,
|
|
19
|
-
202309
|
|
20
|
-
],
|
|
21
|
-
"datasets": [
|
|
22
|
-
{
|
|
23
|
-
"label": "Dataset 1",
|
|
24
|
-
"data": [
|
|
25
|
-
10,
|
|
26
|
-
30,
|
|
27
|
-
50,
|
|
28
|
-
20,
|
|
29
|
-
25,
|
|
30
|
-
44,
|
|
31
|
-
-10
|
|
32
|
-
],
|
|
33
|
-
"borderColor": "#4dc9f6",
|
|
34
|
-
"backgroundColor": "#4dc9f6",
|
|
35
|
-
"trendlineLinear": {
|
|
36
|
-
"colorMin": "#4dc9f6",
|
|
37
|
-
"colorMax": "#4dc9f6",
|
|
38
|
-
"lineStyle": "dotted",
|
|
39
|
-
"width": 2,
|
|
40
|
-
"projection": false
|
|
41
|
-
}
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
"label": "Dataset 2",
|
|
45
|
-
"data": [
|
|
46
|
-
100,
|
|
47
|
-
33,
|
|
48
|
-
22,
|
|
49
|
-
19,
|
|
50
|
-
11,
|
|
51
|
-
49,
|
|
52
|
-
200
|
|
53
|
-
],
|
|
54
|
-
"borderColor": "#f67019",
|
|
55
|
-
"backgroundColor": "#f67019",
|
|
56
|
-
"trendlineLinear": {
|
|
57
|
-
"colorMin": "#f67019",
|
|
58
|
-
"colorMax": "#f67019",
|
|
59
|
-
"lineStyle": "solid",
|
|
60
|
-
"width": 2,
|
|
61
|
-
"projection": false
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
var lineOptions = {
|
|
68
|
-
plugins: {
|
|
69
|
-
legend: {
|
|
70
|
-
display: true,
|
|
71
|
-
labels: {
|
|
72
|
-
fontSize: 10,
|
|
73
|
-
fontColor: "#000",
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
scales: {
|
|
78
|
-
x:
|
|
79
|
-
{
|
|
80
|
-
gridLines: {
|
|
81
|
-
display: true,
|
|
82
|
-
},
|
|
83
|
-
display: true,
|
|
84
|
-
color: "rgba(255, 255, 255, 0.1)",
|
|
85
|
-
},
|
|
86
|
-
y:
|
|
87
|
-
{
|
|
88
|
-
display: false,
|
|
89
|
-
},
|
|
90
|
-
},
|
|
91
|
-
responsive: true,
|
|
92
|
-
maintainAspectRatio: true,
|
|
93
|
-
};
|
|
94
|
-
document.addEventListener("DOMContentLoaded", function(event) {
|
|
95
|
-
new Chart(document.getElementById("line-chart"), {
|
|
96
|
-
type: 'line',
|
|
97
|
-
data: data,
|
|
98
|
-
options:lineOptions
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
</script>
|
|
102
|
-
</head>
|
|
103
|
-
<body>
|
|
104
|
-
<h1>Line Chart</h1>
|
|
105
|
-
|
|
106
|
-
<div style="width: 800px;">
|
|
107
|
-
<canvas id="line-chart"></canvas>
|
|
108
|
-
</div>
|
|
109
|
-
|
|
110
|
-
</body>
|
|
111
|
-
</html>
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
<html>
|
|
2
|
-
|
|
3
|
-
<head>
|
|
4
|
-
<title>Time scale chart.js</title>
|
|
5
|
-
</head>
|
|
6
|
-
<style>
|
|
7
|
-
.chartBox {
|
|
8
|
-
width: 700px
|
|
9
|
-
}
|
|
10
|
-
</style>
|
|
11
|
-
|
|
12
|
-
<body>
|
|
13
|
-
<div class="chartBox">
|
|
14
|
-
<canvas id="myChart"></canvas>
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
|
-
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
18
|
-
|
|
19
|
-
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
|
|
20
|
-
|
|
21
|
-
<script src="./../src/chartjs-plugin-trendline.js"></script>
|
|
22
|
-
|
|
23
|
-
<script>
|
|
24
|
-
const data = {
|
|
25
|
-
labels: [
|
|
26
|
-
"2023-01-01T08:00:00.000Z",
|
|
27
|
-
"2023-01-02T08:00:00.000Z",
|
|
28
|
-
"2023-01-03T08:00:00.000Z",
|
|
29
|
-
"2023-01-04T08:00:00.000Z",
|
|
30
|
-
],
|
|
31
|
-
datasets: [{
|
|
32
|
-
label: "Default",
|
|
33
|
-
data: [65, 59, 80, 81],
|
|
34
|
-
trendlineLinear: {
|
|
35
|
-
colorMin: "red",
|
|
36
|
-
colorMax: "green",
|
|
37
|
-
lineStyle: "dotted",
|
|
38
|
-
width: 2,
|
|
39
|
-
projection: false,
|
|
40
|
-
},
|
|
41
|
-
}],
|
|
42
|
-
};
|
|
43
|
-
const config = {
|
|
44
|
-
type: 'line',
|
|
45
|
-
data,
|
|
46
|
-
options: {
|
|
47
|
-
scales: {
|
|
48
|
-
x: {
|
|
49
|
-
type: 'time',
|
|
50
|
-
time: {
|
|
51
|
-
unit: 'day',
|
|
52
|
-
},
|
|
53
|
-
},
|
|
54
|
-
y: {
|
|
55
|
-
beginAtZero: true
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
const myChart = new Chart(
|
|
61
|
-
document.getElementById('myChart'),
|
|
62
|
-
config,
|
|
63
|
-
);
|
|
64
|
-
</script>
|
|
65
|
-
</body>
|
|
66
|
-
|
|
67
|
-
</html>
|