chartjs-plugin-trendline 2.0.5 → 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.3.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.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.3.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
 
@@ -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
- /*! For license information please see chartjs-plugin-trendline.min.js.LICENSE.txt */
2
- (()=>{var t={460:(t,i)=>{var e={id:"chartjs-plugin-trendline",afterDatasetsDraw:function(t){var i,e;for(var a in t.scales)if("x"==a[0]?e=t.scales[a]:i=t.scales[a],e&&i)break;var r=t.ctx;t.data.datasets.forEach((function(i,a){var n=i.alwaysShowTrendline||t.isDatasetVisible(a);if(i.trendlineLinear&&n&&i.data.length>1){var o=t.getDatasetMeta(a);!function(t,i,e,a,r){var n=e.borderColor||"rgba(169,169,169, .6)",o=e.trendlineLinear.colorMin||n,h=e.trendlineLinear.colorMax||n,l=e.trendlineLinear.width||e.borderWidth,u=e.trendlineLinear.lineStyle||"solid",d=e.trendlineLinear.fillColor;l=void 0!==l?l:3;var m=new s,x=e.data.findIndex((t=>null!=t)),c=e.data.length-1,f=t.data[x].x,X=t.data[c].x,v="object"==typeof e.data[x];e.data.forEach((function(t,i){if(null!=t)if(["time","timeseries"].includes(a.options.type)){var e=null!=t.x?t.x:t.t;void 0!==e?m.add(new Date(e).getTime(),t.y):m.add(i,t)}else v?isNaN(t.x)||isNaN(t.y)?isNaN(t.x)?isNaN(t.y)||m.add(i,t.y):m.add(i,t.x):m.add(t.x,t.y):m.add(i,t)}));var p,y,g=a.getPixelForValue(m.minx),w=r.getPixelForValue(m.f(m.minx));if(e.trendlineLinear.projection&&m.scale()<0){var Y=m.fo();Y<m.minx&&(Y=m.maxx),p=a.getPixelForValue(Y),y=r.getPixelForValue(m.f(Y))}else p=a.getPixelForValue(m.maxx),y=r.getPixelForValue(m.f(m.maxx));v||(g=f,p=X);var L=t.controller.chart.chartArea.bottom,P=t.controller.chart.width;if(w>L){var C=w-L,b=w-y;w=L,g+=P*(C/b)}else y>L&&(C=y-L,b=y-w,y=L,p=P-(p-(P-P*(C/b))));i.lineWidth=l,"dotted"===u?i.setLineDash([2,3]):i.setLineDash([]),i.beginPath(),i.moveTo(g,w),i.lineTo(p,y);var D=i.createLinearGradient(g,w,p,y);y<w?(D.addColorStop(0,h),D.addColorStop(1,o)):(D.addColorStop(0,o),D.addColorStop(1,h)),i.strokeStyle=D,i.stroke(),i.closePath(),!d||(i.fillStyle=d,i.beginPath(),i.moveTo(g,w),i.lineTo(p,y),i.lineTo(p,L),i.lineTo(g,L),i.closePath(),i.fill())}(o,r,i,e,t.scales[o.yAxisID])}})),r.setLineDash([])}};function s(){this.count=0,this.sumX=0,this.sumX2=0,this.sumXY=0,this.sumY=0,this.minx=1e100,this.maxx=-1e100,this.maxy=-1e100}s.prototype={add:function(t,i){t=parseFloat(t),i=parseFloat(i),this.count++,this.sumX+=t,this.sumX2+=t*t,this.sumXY+=t*i,this.sumY+=i,t<this.minx&&(this.minx=t),t>this.maxx&&(this.maxx=t),i>this.maxy&&(this.maxy=i)},f:function(t){t=parseFloat(t);var i=this.count*this.sumX2-this.sumX*this.sumX;return(this.sumX2*this.sumY-this.sumX*this.sumXY)/i+t*((this.count*this.sumXY-this.sumX*this.sumY)/i)},fo:function(){var 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:function(){var 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(e):window.Chart.plugins.register(e));try{t.exports=e}catch(t){}}},i={};!function e(s){var a=i[s];if(void 0!==a)return a.exports;var r=i[s]={exports:{}};return t[s](r,r.exports,e),r.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.0.5
4
- *
5
- * Copyright 2023 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.3.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.3.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
@@ -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.3/dist/chart.umd.js"></script>
9
+ <script src="./../dist/chartjs-plugin-trendline.min.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,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.3.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.0.5",
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,37 +1,38 @@
1
1
  /*!
2
2
  * chartjs-plugin-trendline.js
3
- * Version: 2.0.5
3
+ * Version: 2.1.1
4
4
  *
5
- * Copyright 2023 Marcus Alsterfjord
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
- var pluginTrendlineLinear = {
11
+ import { LineFitter } from './classes/lineFitter.js';
12
+
13
+ const pluginTrendlineLinear = {
12
14
  id: 'chartjs-plugin-trendline',
13
- afterDatasetsDraw: function (chartInstance) {
14
- var yScale;
15
- var xScale;
16
- for (var axis in chartInstance.scales) {
15
+ afterDatasetsDraw: (chartInstance) => {
16
+ let yScale;
17
+ let xScale;
18
+ for (let axis in chartInstance.scales) {
17
19
  if (axis[0] == 'x') xScale = chartInstance.scales[axis];
18
20
  else yScale = chartInstance.scales[axis];
19
21
  if (xScale && yScale) break;
20
22
  }
21
- var ctx = chartInstance.ctx;
23
+ const ctx = chartInstance.ctx;
22
24
 
23
- chartInstance.data.datasets.forEach(function (dataset, index) {
24
- var showTrendline =
25
+ chartInstance.data.datasets.forEach((dataset, index) => {
26
+ const showTrendline =
25
27
  dataset.alwaysShowTrendline ||
26
28
  chartInstance.isDatasetVisible(index);
27
29
 
28
- // TODO: Add support for objects
29
30
  if (
30
31
  dataset.trendlineLinear &&
31
32
  showTrendline &&
32
33
  dataset.data.length > 1
33
34
  ) {
34
- var datasetMeta = chartInstance.getDatasetMeta(index);
35
+ const datasetMeta = chartInstance.getDatasetMeta(index);
35
36
  addFitter(
36
37
  datasetMeta,
37
38
  ctx,
@@ -46,33 +47,35 @@ var pluginTrendlineLinear = {
46
47
  },
47
48
  };
48
49
 
49
- function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
50
- var defaultColor = dataset.borderColor || 'rgba(169,169,169, .6)';
51
- var colorMin = dataset.trendlineLinear.colorMin || defaultColor;
52
- var colorMax = dataset.trendlineLinear.colorMax || defaultColor;
53
- var lineWidth = dataset.trendlineLinear.width || dataset.borderWidth;
54
- var lineStyle = dataset.trendlineLinear.lineStyle || 'solid';
55
- var fillColor = dataset.trendlineLinear.fillColor;
56
-
57
- lineWidth = lineWidth !== undefined ? lineWidth : 3;
58
-
59
- var fitter = new LineFitter();
60
- var firstIndex = dataset.data.findIndex((d) => {
50
+ const addFitter = (datasetMeta, ctx, dataset, xScale, yScale) => {
51
+ let defaultColor = dataset.borderColor || 'rgba(169,169,169, .6)';
52
+ let colorMin = dataset.trendlineLinear.colorMin || defaultColor;
53
+ let colorMax = dataset.trendlineLinear.colorMax || defaultColor;
54
+ let lineWidth = dataset.trendlineLinear.width ?? dataset.borderWidth ?? 3;
55
+ let lineStyle = dataset.trendlineLinear.lineStyle || 'solid';
56
+ let fillColor = dataset.trendlineLinear.fillColor;
57
+
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
+
63
+ let fitter = new LineFitter();
64
+ let firstIndex = dataset.data.findIndex((d) => {
61
65
  return d !== undefined && d !== null;
62
66
  });
63
- var lastIndex = dataset.data.length - 1;
64
- var startPos = datasetMeta.data[firstIndex].x;
65
- var endPos = datasetMeta.data[lastIndex].x;
66
- var xy = typeof dataset.data[firstIndex] === 'object';
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(function (data, index) {
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
- var x = data.x != null ? data.x : data.t;
76
+ let x = data[xAxisKey] != null ? data[xAxisKey] : data.t;
74
77
  if (x !== undefined) {
75
- fitter.add(new Date(x).getTime(), data.y);
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
- var x1 = xScale.getPixelForValue(fitter.minx);
93
- var y1 = yScale.getPixelForValue(fitter.f(fitter.minx));
95
+ let x1 = xScale.getPixelForValue(fitter.minx);
96
+ let y1 = yScale.getPixelForValue(fitter.f(fitter.minx));
94
97
 
95
- var x2;
96
- var y2;
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
- var x2value = fitter.fo();
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
- var drawBottom = datasetMeta.controller.chart.chartArea.bottom;
118
- var chartWidth = datasetMeta.controller.chart.width;
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
- var diff = y1 - drawBottom;
123
- var lineHeight = y1 - y2;
124
- var overlapPercentage = diff / lineHeight;
125
- var addition = chartWidth * overlapPercentage;
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
- var diff = y2 - drawBottom;
132
- var lineHeight = y2 - y1;
133
- var overlapPercentage = diff / lineHeight;
134
- var subtraction = chartWidth - chartWidth * overlapPercentage;
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
- var gradient = ctx.createLinearGradient(x1, y1, x2, y2);
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,56 +176,6 @@ function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
173
176
  ctx.closePath();
174
177
  ctx.fill();
175
178
  }
176
- }
177
-
178
- function LineFitter() {
179
- this.count = 0;
180
- this.sumX = 0;
181
- this.sumX2 = 0;
182
- this.sumXY = 0;
183
- this.sumY = 0;
184
- this.minx = 1e100;
185
- this.maxx = -1e100;
186
- this.maxy = -1e100;
187
- }
188
-
189
- LineFitter.prototype = {
190
- add: function (x, y) {
191
- x = parseFloat(x);
192
- y = parseFloat(y);
193
-
194
- this.count++;
195
- this.sumX += x;
196
- this.sumX2 += x * x;
197
- this.sumXY += x * y;
198
- this.sumY += y;
199
- if (x < this.minx) this.minx = x;
200
- if (x > this.maxx) this.maxx = x;
201
- if (y > this.maxy) this.maxy = y;
202
- },
203
- f: function (x) {
204
- x = parseFloat(x);
205
-
206
- var det = this.count * this.sumX2 - this.sumX * this.sumX;
207
- var offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
208
- var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
209
- return offset + x * scale;
210
- },
211
- fo: function () {
212
- var det = this.count * this.sumX2 - this.sumX * this.sumX;
213
- var offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
214
- var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
215
-
216
- // Get x when y = 0
217
- var xo = -offset / scale;
218
- return xo;
219
- },
220
- scale: function () {
221
- var det = this.count * this.sumX2 - this.sumX * this.sumX;
222
- var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
223
-
224
- return scale;
225
- },
226
179
  };
227
180
 
228
181
  // If we're in the browser and have access to the global Chart obj, register plugin automatically
@@ -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
+ }
@@ -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>