chartjs-plugin-trendline 2.1.0 → 2.1.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/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.0.
4
+ It has been tested with Chart.js version 4.4.3.
5
5
 
6
6
  ## Installation
7
7
 
@@ -10,7 +10,7 @@ It has been tested with Chart.js version 4.4.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.4.0/dist/chart.min.js"></script>
13
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.min.js"></script>
14
14
  <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-trendline"></script>
15
15
  ```
16
16
 
@@ -1,2 +1,2 @@
1
- /*! For license information please see chartjs-plugin-trendline.min.js.LICENSE.txt */
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
+ /*! For license information please see chartjs-plugin-trendline.min.js.LICENSE.txt */
2
+ (()=>{"use strict";var t={228:(t,e,s)=>{class i{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}}t=s.hmd(t);const a={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 i=t.ctx;t.data.datasets.forEach(((e,a)=>{const o=e.alwaysShowTrendline||t.isDatasetVisible(a);if(e.trendlineLinear&&o&&e.data.length>1){const o=t.getDatasetMeta(a);r(o,i,e,s,t.scales[o.yAxisID])}})),i.setLineDash([])}},r=(t,e,s,a,r)=>{let o=s.borderColor||"rgba(169,169,169, .6)",n=s.trendlineLinear.colorMin||o,l=s.trendlineLinear.colorMax||o,h=s.trendlineLinear.width??s.borderWidth??3,d=s.trendlineLinear.lineStyle||"solid",u=s.trendlineLinear.fillColor;const m=t.controller.chart.options,x="object"==typeof m.parsing?m.parsing:void 0,c=s.trendlineLinear.xAxisKey||x?.xAxisKey||"x",p=s.trendlineLinear.yAxisKey||x?.yAxisKey||"y";let f=new i,y=s.data.findIndex((t=>null!=t)),X=s.data.length-1,g=t.data[y][c],w=t.data[X][c],Y="object"==typeof s.data[y];s.data.forEach(((t,e)=>{if(null!=t)if(["time","timeseries"].includes(a.options.type)){let s=null!=t[c]?t[c]:t.t;void 0!==s?f.add(new Date(s).getTime(),t[p]):f.add(e,t)}else Y?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 b,L,P=a.getPixelForValue(f.minx),C=r.getPixelForValue(f.f(f.minx));if(s.trendlineLinear.projection&&f.scale()<0){let t=f.fo();t<f.minx&&(t=f.maxx),b=a.getPixelForValue(t),L=r.getPixelForValue(f.f(t))}else b=a.getPixelForValue(f.maxx),L=r.getPixelForValue(f.f(f.maxx));Y||(P=g,b=w);let S=t.controller.chart.chartArea.bottom,D=t.controller.chart.width;if(C>S){let t=C-S,e=C-L;C=S,P+=D*(t/e)}else if(L>S){let t=L-S,e=L-C;L=S,b=D-(b-(D-D*(t/e)))}e.lineWidth=h,"dotted"===d?e.setLineDash([2,3]):e.setLineDash([]),e.beginPath(),e.moveTo(P,C),e.lineTo(b,L);let F=e.createLinearGradient(P,C,b,L);L<C?(F.addColorStop(0,l),F.addColorStop(1,n)):(F.addColorStop(0,n),F.addColorStop(1,l)),e.strokeStyle=F,e.stroke(),e.closePath(),u&&(e.fillStyle=u,e.beginPath(),e.moveTo(P,C),e.lineTo(b,L),e.lineTo(b,S),e.lineTo(P,S),e.closePath(),e.fill())};"undefined"!=typeof window&&window.Chart&&(window.Chart.hasOwnProperty("register")?window.Chart.register(a):window.Chart.plugins.register(a));try{t.exports=exports=a}catch(t){}}},e={};function s(i){var a=e[i];if(void 0!==a)return a.exports;var r=e[i]={id:i,loaded:!1,exports:{}};return t[i](r,r.exports,s),r.loaded=!0,r.exports}s.hmd=t=>((t=Object.create(t)).children||(t.children=[]),Object.defineProperty(t,"exports",{enumerable:!0,set:()=>{throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+t.id)}}),t),s(228)})();
@@ -1,10 +1,10 @@
1
- /*!
2
- * chartjs-plugin-trendline.js
3
- * Version: 2.1.0
4
- *
5
- * Copyright 2024 Marcus Alsterfjord
6
- * Released under the MIT license
7
- * https://github.com/Makanz/chartjs-plugin-trendline/blob/master/README.md
8
- *
9
- * Mod by: vesal: accept also xy-data so works with scatter
10
- */
1
+ /*!
2
+ * chartjs-plugin-trendline.js
3
+ * Version: 2.1.1
4
+ *
5
+ * Copyright 2024 Marcus Alsterfjord
6
+ * Released under the MIT license
7
+ * https://github.com/Makanz/chartjs-plugin-trendline/blob/master/README.md
8
+ *
9
+ * Mod by: vesal: accept also xy-data so works with scatter
10
+ */
@@ -5,8 +5,8 @@
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.4.0/dist/chart.umd.js"></script>
9
- <script src="./../src/chartjs-plugin-trendline.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.js"></script>
9
+ <script src="./../dist/chartjs-plugin-trendline.min.js"></script>
10
10
  <script>
11
11
  document.addEventListener("DOMContentLoaded", function(event) {
12
12
  // Bar chart
@@ -5,8 +5,8 @@
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.4.0/dist/chart.umd.js"></script>
9
- <script src="./../src/chartjs-plugin-trendline.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.js"></script>
9
+ <script src="./../dist/chartjs-plugin-trendline.min.js"></script>
10
10
  <script>
11
11
  document.addEventListener("DOMContentLoaded", function(event) {
12
12
  // Bar chart
@@ -5,8 +5,8 @@
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>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>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.js"></script>
9
+ <script src="./../dist/chartjs-plugin-trendline.min.js"></script>
10
10
  <script>
11
11
  document.addEventListener("DOMContentLoaded", function(event) {
12
12
  new Chart(document.getElementById("line-chart"), {
@@ -5,8 +5,8 @@
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.4.0/dist/chart.umd.js"></script>
9
- <script src="./../src/chartjs-plugin-trendline.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.3/dist/chart.umd.js"></script>
9
+ <script src="./../dist/chartjs-plugin-trendline.min.js"></script>
10
10
  <script>
11
11
  document.addEventListener("DOMContentLoaded", function(event) {
12
12
  new Chart(document.getElementById("line-chart"), {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chartjs-plugin-trendline",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "Trendline for Chart.js",
5
5
  "main": "src/chartjs-plugin-trendline.js",
6
6
  "scripts": {
@@ -17,7 +17,7 @@
17
17
  },
18
18
  "homepage": "https://github.com/Makanz/chartjs-plugin-trendline#readme",
19
19
  "devDependencies": {
20
- "webpack": "^5.88.2",
20
+ "webpack": "^5.90.0",
21
21
  "webpack-cli": "^5.1.4"
22
22
  }
23
23
  }
@@ -1,6 +1,6 @@
1
1
  /*!
2
2
  * chartjs-plugin-trendline.js
3
- * Version: 2.1.0
3
+ * Version: 2.1.1
4
4
  *
5
5
  * Copyright 2024 Marcus Alsterfjord
6
6
  * Released under the MIT license
@@ -8,6 +8,8 @@
8
8
  *
9
9
  * Mod by: vesal: accept also xy-data so works with scatter
10
10
  */
11
+ import { LineFitter } from './classes/lineFitter.js';
12
+
11
13
  const pluginTrendlineLinear = {
12
14
  id: 'chartjs-plugin-trendline',
13
15
  afterDatasetsDraw: (chartInstance) => {
@@ -49,16 +51,14 @@ const addFitter = (datasetMeta, ctx, dataset, xScale, yScale) => {
49
51
  let defaultColor = dataset.borderColor || 'rgba(169,169,169, .6)';
50
52
  let colorMin = dataset.trendlineLinear.colorMin || defaultColor;
51
53
  let colorMax = dataset.trendlineLinear.colorMax || defaultColor;
52
- let lineWidth = dataset.trendlineLinear.width || dataset.borderWidth;
54
+ let lineWidth = dataset.trendlineLinear.width ?? dataset.borderWidth ?? 3;
53
55
  let lineStyle = dataset.trendlineLinear.lineStyle || 'solid';
54
56
  let fillColor = dataset.trendlineLinear.fillColor;
55
57
 
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";
60
-
61
- lineWidth = lineWidth !== undefined ? lineWidth : 3;
58
+ const chartOptions = datasetMeta.controller.chart.options;
59
+ const parsingOptions = typeof chartOptions.parsing === 'object' ? chartOptions.parsing : undefined;
60
+ const xAxisKey = dataset.trendlineLinear.xAxisKey || parsingOptions?.xAxisKey || 'x';
61
+ const yAxisKey = dataset.trendlineLinear.yAxisKey || parsingOptions?.yAxisKey || 'y';
62
62
 
63
63
  let fitter = new LineFitter();
64
64
  let firstIndex = dataset.data.findIndex((d) => {
@@ -178,59 +178,6 @@ const addFitter = (datasetMeta, ctx, dataset, xScale, yScale) => {
178
178
  }
179
179
  };
180
180
 
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
- }
192
-
193
- add(x, y) {
194
- x = parseFloat(x);
195
- y = parseFloat(y);
196
-
197
- this.count++;
198
- this.sumX += x;
199
- this.sumX2 += x * x;
200
- this.sumXY += x * y;
201
- this.sumY += y;
202
- if (x < this.minx) this.minx = x;
203
- if (x > this.maxx) this.maxx = x;
204
- if (y > this.maxy) this.maxy = y;
205
- }
206
-
207
- f(x) {
208
- x = parseFloat(x);
209
-
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;
213
- return offset + x * scale;
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;
220
-
221
- // Get x when y = 0
222
- let xo = -offset / scale;
223
- return xo;
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;
229
-
230
- return scale;
231
- }
232
- }
233
-
234
181
  // If we're in the browser and have access to the global Chart obj, register plugin automatically
235
182
  if (typeof window !== 'undefined' && window.Chart) {
236
183
  if (window.Chart.hasOwnProperty('register')) {
@@ -0,0 +1,52 @@
1
+ export class LineFitter {
2
+ constructor() {
3
+ this.count = 0;
4
+ this.sumX = 0;
5
+ this.sumX2 = 0;
6
+ this.sumXY = 0;
7
+ this.sumY = 0;
8
+ this.minx = 1e100;
9
+ this.maxx = -1e100;
10
+ this.maxy = -1e100;
11
+ }
12
+
13
+ add = (x, y) => {
14
+ x = parseFloat(x);
15
+ y = parseFloat(y);
16
+
17
+ this.count++;
18
+ this.sumX += x;
19
+ this.sumX2 += x * x;
20
+ this.sumXY += x * y;
21
+ this.sumY += y;
22
+ if (x < this.minx) this.minx = x;
23
+ if (x > this.maxx) this.maxx = x;
24
+ if (y > this.maxy) this.maxy = y;
25
+ };
26
+
27
+ f = (x) => {
28
+ x = parseFloat(x);
29
+
30
+ let det = this.count * this.sumX2 - this.sumX * this.sumX;
31
+ let offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
32
+ let scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
33
+ return offset + x * scale;
34
+ };
35
+
36
+ fo = () => {
37
+ let det = this.count * this.sumX2 - this.sumX * this.sumX;
38
+ let offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
39
+ let scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
40
+
41
+ // Get x when y = 0
42
+ let xo = -offset / scale;
43
+ return xo;
44
+ };
45
+
46
+ scale = () => {
47
+ let det = this.count * this.sumX2 - this.sumX * this.sumX;
48
+ let scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
49
+
50
+ return scale;
51
+ };
52
+ }