chartjs-plugin-trendline 1.0.0 → 2.0.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/.prettierrc ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "trailingComma": "es5",
3
+ "tabWidth": 4,
4
+ "semi": true,
5
+ "singleQuote": true
6
+ }
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2019 Marcus Alsterfjord
3
+ Copyright (c) 2022 Marcus Alsterfjord
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -9,7 +9,7 @@ This plugin draws an linear trendline in your Chart. Made for Chart.js 3.X
9
9
  Load ChartJS first, then the plugin which will automatically register itself with ChartJS
10
10
 
11
11
  ```html
12
- <script src="https://cdn.jsdelivr.net/npm/chart.js@3.5.1/dist/chart.min.js"></script>
12
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@3.8.0/dist/chart.min.js"></script>
13
13
  <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-trendline"></script>
14
14
  ```
15
15
 
@@ -20,8 +20,8 @@ Install & import the plugin via npm:
20
20
  `npm i chart.js chartjs-plugin-trendline`
21
21
 
22
22
  ```js
23
- import ChartJS from "chart.js";
24
- import chartTrendline from "chartjs-plugin-trendline";
23
+ import ChartJS from 'chart.js';
24
+ import chartTrendline from 'chartjs-plugin-trendline';
25
25
 
26
26
  ChartJS.plugins.register(chartTrendline);
27
27
  ```
@@ -33,9 +33,11 @@ To configure the trendline plugin you simply add a new config options to your da
33
33
  ```javascript
34
34
  {
35
35
  trendlineLinear: {
36
- style: "rgba(255,105,180, .8)",
36
+ colorMin: "red",
37
+ colorMax: "green",
37
38
  lineStyle: "dotted|solid",
38
- width: 2
39
+ width: 2,
40
+ projection: true|false (optional)
39
41
  }
40
42
  }
41
43
  ```
@@ -1 +1,2 @@
1
- var pluginTrendlineLinear={id:"chartjs-plugin-trendline",afterDraw:function(a){var t,s;for(var i in a.scales)if("x"==i[0]?s=a.scales[i]:t=a.scales[i],s&&t)break;var r=a.ctx;a.data.datasets.forEach(function(t,i){if(t.trendlineLinear&&a.isDatasetVisible(i)&&0!=t.data.length){var e=a.getDatasetMeta(i);addFitter(e,r,t,s,a.scales[e.yAxisID])}}),r.setLineDash([])}};function addFitter(t,i,e,a,s){var r=e.trendlineLinear.style||e.borderColor,n=e.trendlineLinear.width||e.borderWidth,o=e.trendlineLinear.lineStyle||"solid";r=void 0!==r?r:"rgba(169,169,169, .6)",n=void 0!==n?n:3;var l=new LineFitter,d=e.data.length-1,h=t.data[0].x,u=t.data[d].x,m=!1;e.data&&"object"==typeof e.data[0]&&(m=!0),e.data.forEach(function(t,i){if(null!=t)if("time"===a.options.type){var e=null!=t.x?t.x:t.t;l.add(new Date(e).getTime(),t.y)}else m?l.add(t.x,t.y):l.add(i,t)});var x=a.getPixelForValue(l.minx),c=a.getPixelForValue(l.maxx),f=s.getPixelForValue(l.f(l.minx)),g=s.getPixelForValue(l.f(l.maxx));m||(x=h,c=u);var p=t.controller.chart.chartArea.bottom,v=t.controller.chart.width;if(p<f){var w=f-p,X=f-g;f=p,x+=v*(w/X)}else if(p<g){w=g-p,X=g-f;g=p,c=v-(c-(v-v*(w/X)))}i.lineWidth=n,"dotted"===o&&i.setLineDash([2,3]),i.beginPath(),i.moveTo(x,f),i.lineTo(c,g),i.strokeStyle=r,i.stroke()}function LineFitter(){this.count=0,this.sumX=0,this.sumX2=0,this.sumXY=0,this.sumY=0,this.minx=1e100,this.maxx=-1e100}LineFitter.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)},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)}},void 0!==typeof window&&window.Chart&&(window.Chart.hasOwnProperty("register")?window.Chart.register(pluginTrendlineLinear):window.Chart.plugins.register(pluginTrendlineLinear));try{module.exports=exports=pluginTrendlineLinear}catch(t){}
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){if(i.trendlineLinear&&t.isDatasetVisible(a)&&0!=i.data.length){var n=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,c=e.data.findIndex((t=>null!=t)),x=e.data.length-1,f=t.data[c].x,X=t.data[x].x,v="object"==typeof e.data[c];e.data.forEach((function(t,i){if(null!=t)if("time"===a.options.type){var e=null!=t.x?t.x:t.t;m.add(new Date(e).getTime(),t.y)}else v?m.add(t.x,t.y):m.add(i,t)}));var p,g,w=a.getPixelForValue(m.minx),y=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),g=r.getPixelForValue(m.f(Y))}else p=a.getPixelForValue(m.maxx),g=r.getPixelForValue(m.f(m.maxx));v||(w=f,p=X);var P=t.controller.chart.chartArea.bottom,C=t.controller.chart.width;if(y>P){var L=y-P,b=y-g;y=P,w+=C*(L/b)}else g>P&&(L=g-P,b=g-y,g=P,p=C-(p-(C-C*(L/b))));i.lineWidth=l,"dotted"===u&&i.setLineDash([2,3]),i.beginPath(),i.moveTo(w,y),i.lineTo(p,g);var F=i.createLinearGradient(w,y,p,g);g<y?(F.addColorStop(0,h),F.addColorStop(1,o)):(F.addColorStop(0,o),F.addColorStop(1,h)),i.strokeStyle=F,i.stroke(),i.closePath(),!d||(i.fillStyle=d,i.beginPath(),i.moveTo(w,y),i.lineTo(p,g),i.lineTo(p,P),i.lineTo(w,P),i.closePath(),i.fill())}(n,r,i,e,t.scales[n.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)})();
@@ -0,0 +1,10 @@
1
+ /*!
2
+ * chartjs-plugin-trendline.js
3
+ * Version: 2.0.0
4
+ *
5
+ * Copyright 2022 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@3.5.1/dist/chart.min.js"></script>
9
- <script src="../src/chartjs-plugin-trendline.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@3.8.0/dist/chart.min.js"></script>
9
+ <script src="./../src/chartjs-plugin-trendline.js"></script>
10
10
  <script>
11
11
  document.addEventListener("DOMContentLoaded", function(event) {
12
12
  // Bar chart
@@ -20,7 +20,7 @@
20
20
  backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
21
21
  data: [2478,5267,734,784,433],
22
22
  trendlineLinear: {
23
- style: "rgba(255,105,180, .8)",
23
+ colorMin: "rgba(255,105,180, .8)",
24
24
  lineStyle: "dotted",
25
25
  width: 2
26
26
  }
@@ -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@3.5.1/dist/chart.min.js"></script>
9
- <script src="../src/chartjs-plugin-trendline.js"></script>
8
+ <script src="https://cdn.jsdelivr.net/npm/chart.js@3.8.0/dist/chart.min.js"></script>
9
+ <script src="./../src/chartjs-plugin-trendline.js"></script>
10
10
  <script>
11
11
  document.addEventListener("DOMContentLoaded", function(event) {
12
12
  new Chart(document.getElementById("line-chart"), {
@@ -19,7 +19,7 @@
19
19
  borderColor: "#3e95cd",
20
20
  fill: false,
21
21
  trendlineLinear: {
22
- style: "#3e95cd",
22
+ colorMin: "#3e95cd",
23
23
  lineStyle: "line",
24
24
  width: 1
25
25
  }
@@ -29,7 +29,8 @@
29
29
  borderColor: "#8e5ea2",
30
30
  fill: false,
31
31
  trendlineLinear: {
32
- style: "#8e5ea2",
32
+ colorMin: "red",
33
+ colorMax: "green",
33
34
  lineStyle: "line",
34
35
  width: 1
35
36
  }
@@ -0,0 +1,55 @@
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>XYlineChart Projection Example</title>
8
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.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
+ datasets: [{
16
+ data: [{x: 0, y: 30}, {x: 5, y:25}, {x: 10, y: 23}],
17
+ label: "Count",
18
+ borderColor: "#3e95cd",
19
+ fill: false,
20
+ trendlineLinear: {
21
+ colorMin: "#3e95cd",
22
+ lineStyle: "line",
23
+ width: 1,
24
+ projection: true
25
+ }
26
+ }, {
27
+ data: [{x: 60, y: 0}],
28
+ borderColor: "black",
29
+ label: "Goal",
30
+ fill: false
31
+ }]
32
+ },
33
+ options: {
34
+ title: {
35
+ display: true,
36
+ text: 'Cigarettes per days',
37
+ },
38
+ maintainAspectRatio: false,
39
+ responsive: true,
40
+ scales: {
41
+ xAxes: [{ type: 'linear', position: 'bottom', scaleLabel: { labelString: 'days', display: true}}],
42
+ yAxes: [{ type: 'linear', position: 'left', scaleLabel: { labelString: 'cigarretts/day', display: true}, display: true }],
43
+ }
44
+ }
45
+ });
46
+ });
47
+ </script>
48
+ </head>
49
+ <body>
50
+ <h1>X/Y Chart with trendline projection on x axis</h1>
51
+ <canvas id="line-chart" width="600" height="450"></canvas>
52
+
53
+ <p>Using example code from <a href="http://tobiasahlin.com/blog/chartjs-charts-to-get-you-started/" target="_blank">tobiasahlin.com.</a></p>
54
+ </body>
55
+ </html>
package/package.json CHANGED
@@ -1,12 +1,10 @@
1
1
  {
2
2
  "name": "chartjs-plugin-trendline",
3
- "version": "1.0.0",
3
+ "version": "2.0.0",
4
4
  "description": "Trendline for Chart.js",
5
5
  "main": "src/chartjs-plugin-trendline.js",
6
6
  "scripts": {
7
- "build": "gulp",
8
- "bump-minor": "gulp bump-minor",
9
- "bump-patch": "gulp bump-patch"
7
+ "build": "webpack --mode=production"
10
8
  },
11
9
  "repository": {
12
10
  "type": "git",
@@ -19,11 +17,7 @@
19
17
  },
20
18
  "homepage": "https://github.com/Makanz/chartjs-plugin-trendline#readme",
21
19
  "devDependencies": {
22
- "del": "^6.0.0",
23
- "gulp": "^4.0.2",
24
- "gulp-bump": "^3.2.0",
25
- "gulp-rename": "^2.0.0",
26
- "gulp-uglify": "^3.0.2",
27
- "pump": "^3.0.0"
20
+ "webpack": "^5.73.0",
21
+ "webpack-cli": "^4.10.0"
28
22
  }
29
23
  }
@@ -1,106 +1,158 @@
1
1
  /*!
2
2
  * chartjs-plugin-trendline.js
3
- * Version: 1.0.0
3
+ * Version: 2.0.0
4
4
  *
5
- * Copyright 2021 Marcus Alsterfjord
5
+ * Copyright 2022 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
  var pluginTrendlineLinear = {
12
- id: "chartjs-plugin-trendline",
13
- afterDraw: function(chartInstance) {
12
+ id: 'chartjs-plugin-trendline',
13
+ afterDatasetsDraw: function (chartInstance) {
14
14
  var yScale;
15
15
  var xScale;
16
16
  for (var axis in chartInstance.scales) {
17
- if ( axis[0] == 'x')
18
- xScale = chartInstance.scales[axis];
19
- else
20
- yScale = chartInstance.scales[axis];
21
- if ( xScale && yScale ) break;
17
+ if (axis[0] == 'x') xScale = chartInstance.scales[axis];
18
+ else yScale = chartInstance.scales[axis];
19
+ if (xScale && yScale) break;
22
20
  }
23
21
  var ctx = chartInstance.ctx;
24
22
 
25
- chartInstance.data.datasets.forEach(function(dataset, index) {
26
- if (dataset.trendlineLinear && chartInstance.isDatasetVisible(index) && dataset.data.length != 0) {
23
+ chartInstance.data.datasets.forEach(function (dataset, index) {
24
+ if (
25
+ dataset.trendlineLinear &&
26
+ chartInstance.isDatasetVisible(index) &&
27
+ dataset.data.length != 0
28
+ ) {
27
29
  var datasetMeta = chartInstance.getDatasetMeta(index);
28
- addFitter(datasetMeta, ctx, dataset, xScale, chartInstance.scales[datasetMeta.yAxisID]);
30
+ addFitter(
31
+ datasetMeta,
32
+ ctx,
33
+ dataset,
34
+ xScale,
35
+ chartInstance.scales[datasetMeta.yAxisID]
36
+ );
29
37
  }
30
38
  });
31
39
 
32
40
  ctx.setLineDash([]);
33
- }
41
+ },
34
42
  };
35
43
 
36
44
  function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
37
- var style = dataset.trendlineLinear.style || dataset.borderColor;
45
+ var defaultColor = dataset.borderColor || 'rgba(169,169,169, .6)';
46
+ var colorMin = dataset.trendlineLinear.colorMin || defaultColor;
47
+ var colorMax = dataset.trendlineLinear.colorMax || defaultColor;
38
48
  var lineWidth = dataset.trendlineLinear.width || dataset.borderWidth;
39
- var lineStyle = dataset.trendlineLinear.lineStyle || "solid";
49
+ var lineStyle = dataset.trendlineLinear.lineStyle || 'solid';
50
+ var fillColor = dataset.trendlineLinear.fillColor;
40
51
 
41
- style = (style !== undefined) ? style : "rgba(169,169,169, .6)";
42
- lineWidth = (lineWidth !== undefined) ? lineWidth : 3;
52
+ lineWidth = lineWidth !== undefined ? lineWidth : 3;
43
53
 
44
54
  var fitter = new LineFitter();
55
+ var firstIndex = dataset.data.findIndex((d) => {
56
+ return d !== undefined && d !== null;
57
+ });
45
58
  var lastIndex = dataset.data.length - 1;
46
- var startPos = datasetMeta.data[0].x;
59
+ var startPos = datasetMeta.data[firstIndex].x;
47
60
  var endPos = datasetMeta.data[lastIndex].x;
61
+ var xy = typeof dataset.data[firstIndex] === 'object';
48
62
 
49
- var xy = false;
50
- if ( dataset.data && typeof dataset.data[0] === 'object') xy = true;
51
-
52
- dataset.data.forEach(function(data, index) {
53
-
54
- if(data == null)
55
- return;
63
+ dataset.data.forEach(function (data, index) {
64
+ if (data == null) return;
56
65
 
57
- if (xScale.options.type === "time") {
66
+ if (xScale.options.type === 'time') {
58
67
  var x = data.x != null ? data.x : data.t;
59
68
  fitter.add(new Date(x).getTime(), data.y);
60
- }
61
- else if (xy) {
69
+ } else if (xy) {
62
70
  fitter.add(data.x, data.y);
63
- }
64
- else {
71
+ } else {
65
72
  fitter.add(index, data);
66
73
  }
67
-
68
74
  });
69
75
 
70
76
  var x1 = xScale.getPixelForValue(fitter.minx);
71
- var x2 = xScale.getPixelForValue(fitter.maxx);
72
77
  var y1 = yScale.getPixelForValue(fitter.f(fitter.minx));
73
- var y2 = yScale.getPixelForValue(fitter.f(fitter.maxx));
74
- if ( !xy ) { x1 = startPos; x2 = endPos; }
75
-
78
+
79
+ var x2;
80
+ var y2;
81
+
82
+ // Project only on x axes, do not project if trendline will never hit x axes
83
+ if (dataset.trendlineLinear.projection && fitter.scale() < 0) {
84
+ // X
85
+ var x2value = fitter.fo();
86
+ if (x2value < fitter.minx) x2value = fitter.maxx;
87
+ x2 = xScale.getPixelForValue(x2value);
88
+
89
+ // Y
90
+ y2 = yScale.getPixelForValue(fitter.f(x2value));
91
+ } else {
92
+ x2 = xScale.getPixelForValue(fitter.maxx);
93
+ y2 = yScale.getPixelForValue(fitter.f(fitter.maxx));
94
+ }
95
+
96
+ if (!xy) {
97
+ x1 = startPos;
98
+ x2 = endPos;
99
+ }
100
+
76
101
  var drawBottom = datasetMeta.controller.chart.chartArea.bottom;
77
102
  var chartWidth = datasetMeta.controller.chart.width;
78
103
 
79
- if(y1 > drawBottom) { // Left side is below zero
104
+ if (y1 > drawBottom) {
105
+ // Left side is below zero
80
106
  var diff = y1 - drawBottom;
81
107
  var lineHeight = y1 - y2;
82
108
  var overlapPercentage = diff / lineHeight;
83
109
  var addition = chartWidth * overlapPercentage;
84
110
 
85
111
  y1 = drawBottom;
86
- x1 = (x1 + addition);
87
- } else if(y2 > drawBottom) { // right side is below zero
112
+ x1 = x1 + addition;
113
+ } else if (y2 > drawBottom) {
114
+ // right side is below zero
88
115
  var diff = y2 - drawBottom;
89
116
  var lineHeight = y2 - y1;
90
117
  var overlapPercentage = diff / lineHeight;
91
- var subtraction = chartWidth - (chartWidth * overlapPercentage);
118
+ var subtraction = chartWidth - chartWidth * overlapPercentage;
92
119
 
93
120
  y2 = drawBottom;
94
121
  x2 = chartWidth - (x2 - subtraction);
95
122
  }
96
123
 
97
124
  ctx.lineWidth = lineWidth;
98
- if (lineStyle === "dotted") { ctx.setLineDash([2, 3]); }
125
+ if (lineStyle === 'dotted') {
126
+ ctx.setLineDash([2, 3]);
127
+ }
99
128
  ctx.beginPath();
100
129
  ctx.moveTo(x1, y1);
101
130
  ctx.lineTo(x2, y2);
102
- ctx.strokeStyle = style;
131
+
132
+ var gradient= ctx.createLinearGradient(x1, y1, x2, y2);
133
+ if (y2 < y1) {
134
+ gradient.addColorStop(0, colorMax);
135
+ gradient.addColorStop(1, colorMin);
136
+ } else{
137
+ gradient.addColorStop(0, colorMin);
138
+ gradient.addColorStop(1, colorMax);
139
+ }
140
+
141
+ ctx.strokeStyle = gradient;
142
+
103
143
  ctx.stroke();
144
+ ctx.closePath();
145
+
146
+ if (!!fillColor) {
147
+ ctx.fillStyle = fillColor;
148
+ ctx.beginPath();
149
+ ctx.moveTo(x1, y1);
150
+ ctx.lineTo(x2, y2);
151
+ ctx.lineTo(x2, drawBottom);
152
+ ctx.lineTo(x1, drawBottom);
153
+ ctx.closePath();
154
+ ctx.fill();
155
+ }
104
156
  }
105
157
 
106
158
  function LineFitter() {
@@ -111,33 +163,50 @@ function LineFitter() {
111
163
  this.sumY = 0;
112
164
  this.minx = 1e100;
113
165
  this.maxx = -1e100;
166
+ this.maxy = -1e100;
114
167
  }
115
168
 
116
169
  LineFitter.prototype = {
117
- 'add': function (x, y) {
170
+ add: function (x, y) {
118
171
  x = parseFloat(x);
119
- y = parseFloat(y);
120
-
172
+ y = parseFloat(y);
173
+
121
174
  this.count++;
122
175
  this.sumX += x;
123
176
  this.sumX2 += x * x;
124
177
  this.sumXY += x * y;
125
178
  this.sumY += y;
126
- if ( x < this.minx ) this.minx = x;
127
- if ( x > this.maxx ) this.maxx = x;
179
+ if (x < this.minx) this.minx = x;
180
+ if (x > this.maxx) this.maxx = x;
181
+ if (y > this.maxy) this.maxy = y;
128
182
  },
129
- 'f': function (x) {
183
+ f: function (x) {
130
184
  x = parseFloat(x);
131
-
185
+
132
186
  var det = this.count * this.sumX2 - this.sumX * this.sumX;
133
187
  var offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
134
188
  var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
135
189
  return offset + x * scale;
136
- }
190
+ },
191
+ fo: function () {
192
+ var det = this.count * this.sumX2 - this.sumX * this.sumX;
193
+ var offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
194
+ var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
195
+
196
+ // Get x when y = 0
197
+ var xo = -offset / scale;
198
+ return xo;
199
+ },
200
+ scale: function () {
201
+ var det = this.count * this.sumX2 - this.sumX * this.sumX;
202
+ var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
203
+
204
+ return scale;
205
+ },
137
206
  };
138
207
 
139
208
  // If we're in the browser and have access to the global Chart obj, register plugin automatically
140
- if (typeof window !== undefined && window.Chart) {
209
+ if (typeof window !== 'undefined' && window.Chart) {
141
210
  if (window.Chart.hasOwnProperty('register')) {
142
211
  window.Chart.register(pluginTrendlineLinear);
143
212
  } else {
@@ -0,0 +1,9 @@
1
+ const path = require('path');
2
+
3
+ module.exports = {
4
+ entry: './src/chartjs-plugin-trendline.js',
5
+ output: {
6
+ filename: 'chartjs-plugin-trendline.min.js',
7
+ path: path.resolve(__dirname, 'dist'),
8
+ },
9
+ };
package/gulpfile.js DELETED
@@ -1,37 +0,0 @@
1
- var gulp = require('gulp');
2
- var uglify = require('gulp-uglify');
3
- var pump = require('pump');
4
- var rename = require('gulp-rename');
5
- var del = require('del');
6
- var bump = require('gulp-bump');
7
-
8
- gulp.task('clean', function () {
9
- return del([
10
- 'dist/',
11
- ]);
12
- });
13
-
14
- gulp.task('compress', function (cb) {
15
- pump([
16
- gulp.src('src/*.js'),
17
- uglify(),
18
- rename('chartjs-plugin-trendline.min.js'),
19
- gulp.dest('dist/')
20
- ],
21
- cb
22
- );
23
- });
24
-
25
- gulp.task('bump-minor', function(){
26
- return gulp.src(['./package.json', './src/chartjs-plugin-trendline.js'], {base: './'})
27
- .pipe(bump({type:'minor'}))
28
- .pipe(gulp.dest('./'));
29
- });
30
-
31
- gulp.task('bump-patch', function(){
32
- return gulp.src(['./package.json', './src/chartjs-plugin-trendline.js'], {base: './'})
33
- .pipe(bump({type:'patch'}))
34
- .pipe(gulp.dest('./'));
35
- });
36
-
37
- gulp.task('default', gulp.series('clean', 'compress'));