Skip to content

Commit

Permalink
Can use also XY data for scatter-graphs
Browse files Browse the repository at this point in the history
  • Loading branch information
vesal committed Aug 1, 2019
1 parent e1db91d commit a31ca31
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 12 deletions.
75 changes: 75 additions & 0 deletions example/ScatterChart.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>LineChart Example</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<script src="../src/chartjs-plugin-trendline.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
new Chart(document.getElementById("line-chart"), {
type: 'scatter',
data: {
datasets: [{
data: [{x: 1500, y: 86},{x: 1600, y: 114},{x: 1700, y: 106},{x: 1750, y: 106},{x: 1800, y: 107},{x: 1850, y: 111},{x: 1900, y: 133},{x: 1950, y: 221},{x: 1999, y: 783},{x: 2050, y: 2478}],
label: "Africa",
borderColor: "#3e95cd",
fill: false,
trendlineLinear: {
style: "#3e95cd",
lineStyle: "line",
width: 1
}
}, {
data: [{x: 1500, y: 282},{x: 1600, y: 350},{x: 1700, y: 411},{x: 1750, y: 502},{x: 1800, y: 635},{x: 1850, y: 809},{x: 1900, y: 947},{x: 1950, y: 1402},{x: 1999, y: 3700},{x: 2050, y: 5267}],
label: "Asia",
borderColor: "#8e5ea2",
fill: false,
trendlineLinear: {
style: "#8e5ea2",
lineStyle: "line",
width: 1
}
}, {
data: [{x: 1500, y: 168},{x: 1600, y: 170},{x: 1700, y: 178},{x: 1750, y: 190},{x: 1800, y: 203},{x: 1850, y: 276},{x: 1900, y: 408},{x: 1950, y: 547},{x: 1999, y: 675},{x: 2050, y: 734}],
label: "Europe",
borderColor: "#3cba9f",
fill: false
}, {
data: [{x: 1500, y: 40},{x: 1600, y: 20},{x: 1700, y: 10},{x: 1750, y: 16},{x: 1800, y: 24},{x: 1850, y: 38},{x: 1900, y: 74},{x: 1950, y: 167},{x: 1999, y: 508},{x: 2050, y: 784}],
label: "Latin America",
borderColor: "#e8c3b9",
fill: false
}, {
data: [{x: 1500, y: 6},{x: 1600, y: 3},{x: 1700, y: 2},{x: 1750, y: 2},{x: 1800, y: 7},{x: 1850, y: 26},{x: 1900, y: 82},{x: 1950, y: 172},{x: 1999, y: 312},{x: 2050, y: 433}],
label: "North America",
borderColor: "#c45850",
fill: false
}
]
},
options: {
title: {
display: true,
text: 'World population per region (in millions)',
},
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: [{ type: 'linear', position: 'bottom', scaleLabel: { labelString: 'year', display: true} }],
yAxes: [{ type: 'linear', position: 'left', scaleLabel: { labelString: 'population/1M', display: true}, display: true }],
}
}
});
});
</script>
</head>
<body>
<h1>Line Chart</h1>
<canvas id="line-chart" width="600" height="450"></canvas>

<p>Using example code from <a href="http://tobiasahlin.com/blog/chartjs-charts-to-get-you-started/" target="_blank">tobiasahlin.com.</a></p>
</body>
</html>
75 changes: 75 additions & 0 deletions example/XYlineChart.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>LineChart Example</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<script src="../src/chartjs-plugin-trendline.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
new Chart(document.getElementById("line-chart"), {
type: 'line',
data: {
datasets: [{
data: [{x: 1500, y: 86},{x: 1600, y: 114},{x: 1700, y: 106},{x: 1750, y: 106},{x: 1800, y: 107},{x: 1850, y: 111},{x: 1900, y: 133},{x: 1950, y: 221},{x: 1999, y: 783},{x: 2050, y: 2478}],
label: "Africa",
borderColor: "#3e95cd",
fill: false,
trendlineLinear: {
style: "#3e95cd",
lineStyle: "line",
width: 1
}
}, {
data: [{x: 1500, y: 282},{x: 1600, y: 350},{x: 1700, y: 411},{x: 1750, y: 502},{x: 1800, y: 635},{x: 1850, y: 809},{x: 1900, y: 947},{x: 1950, y: 1402},{x: 1999, y: 3700},{x: 2050, y: 5267}],
label: "Asia",
borderColor: "#8e5ea2",
fill: false,
trendlineLinear: {
style: "#8e5ea2",
lineStyle: "line",
width: 1
}
}, {
data: [{x: 1500, y: 168},{x: 1600, y: 170},{x: 1700, y: 178},{x: 1750, y: 190},{x: 1800, y: 203},{x: 1850, y: 276},{x: 1900, y: 408},{x: 1950, y: 547},{x: 1999, y: 675},{x: 2050, y: 734}],
label: "Europe",
borderColor: "#3cba9f",
fill: false
}, {
data: [{x: 1500, y: 40},{x: 1600, y: 20},{x: 1700, y: 10},{x: 1750, y: 16},{x: 1800, y: 24},{x: 1850, y: 38},{x: 1900, y: 74},{x: 1950, y: 167},{x: 1999, y: 508},{x: 2050, y: 784}],
label: "Latin America",
borderColor: "#e8c3b9",
fill: false
}, {
data: [{x: 1500, y: 6},{x: 1600, y: 3},{x: 1700, y: 2},{x: 1750, y: 2},{x: 1800, y: 7},{x: 1850, y: 26},{x: 1900, y: 82},{x: 1950, y: 172},{x: 1999, y: 312},{x: 2050, y: 433}],
label: "North America",
borderColor: "#c45850",
fill: false
}
]
},
options: {
title: {
display: true,
text: 'World population per region (in millions)',
},
maintainAspectRatio: false,
responsive: true,
scales: {
xAxes: [{ type: 'linear', position: 'bottom', scaleLabel: { labelString: 'year', display: true} }],
yAxes: [{ type: 'linear', position: 'left', scaleLabel: { labelString: 'population/1M', display: true}, display: true }],
}
}
});
});
</script>
</head>
<body>
<h1>Line Chart</h1>
<canvas id="line-chart" width="600" height="450"></canvas>

<p>Using example code from <a href="http://tobiasahlin.com/blog/chartjs-charts-to-get-you-started/" target="_blank">tobiasahlin.com.</a></p>
</body>
</html>
46 changes: 34 additions & 12 deletions src/chartjs-plugin-trendline.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,65 @@
* Copyright 2017 Marcus Alsterfjord
* Released under the MIT license
* https://github.com/Makanz/chartjs-plugin-trendline/blob/master/README.md
*
* Mod by: vesal: accept also xy-data so works with scatter
*/
var pluginTrendlineLinear = {
beforeDraw: function(chartInstance) {
var yScale = chartInstance.scales["y-axis-0"];
var yScale;
var xScale;
for (let axis in chartInstance.scales) {
if ( axis[0] == 'x')
xScale = chartInstance.scales[axis];
else
yScale = chartInstance.scales[axis];
if ( xScale && yScale ) break;
}
var ctx = chartInstance.chart.ctx;

chartInstance.data.datasets.forEach(function(dataset, index) {
if (dataset.trendlineLinear && chartInstance.isDatasetVisible(index)) {
var datasetMeta = chartInstance.getDatasetMeta(index);
addFitter(datasetMeta, ctx, dataset, yScale);
addFitter(datasetMeta, ctx, dataset, xScale, yScale);
}
});

ctx.setLineDash([]);
}
};

function addFitter(datasetMeta, ctx, dataset, yScale) {
function addFitter(datasetMeta, ctx, dataset, xScale, yScale) {
var style = dataset.trendlineLinear.style || dataset.borderColor;
var lineWidth = dataset.trendlineLinear.width || dataset.borderWidth;
var lineStyle = dataset.trendlineLinear.lineStyle || "solid";

style = (style !== undefined) ? style : "rgba(169,169,169, .6)";
lineWidth = (lineWidth !== undefined) ? lineWidth : 3;

var fitter = new LineFitter();
var lastIndex = dataset.data.length - 1;
var startPos = datasetMeta.data[0]._model.x;
var endPos = datasetMeta.data[lastIndex]._model.x;
var fitter = new LineFitter();

var xy = false;
if ( dataset.data && typeof dataset.data[0] === 'object') xy = true;

dataset.data.forEach(function(data, index) {
fitter.add(index, data);
if ( xy ) fitter.add(data.x, data.y);
else fitter.add(index, data);
});

var x1 = xScale.getPixelForValue(fitter.minx);
var x2 = xScale.getPixelForValue(fitter.maxx);
var y1 = yScale.getPixelForValue(fitter.f(fitter.minx));
var y2 = yScale.getPixelForValue(fitter.f(fitter.maxx));
if ( !xy ) { x1 = startPos; x2 = endPos; }

ctx.lineWidth = lineWidth;
if (lineStyle === "dotted") {
ctx.setLineDash([2, 3]);
}
if (lineStyle === "dotted") { ctx.setLineDash([2, 3]); }
ctx.beginPath();
ctx.moveTo(startPos, yScale.getPixelForValue(fitter.project(0)));
ctx.lineTo(endPos, yScale.getPixelForValue(fitter.project(lastIndex)));
ctx.moveTo(x1, y1);
ctx.lineTo(x2, y2);
ctx.strokeStyle = style;
ctx.stroke();
}
Expand All @@ -58,6 +76,8 @@ function LineFitter() {
this.sumX2 = 0;
this.sumXY = 0;
this.sumY = 0;
this.minx = 1e100;
this.maxx = -1e100;
}

LineFitter.prototype = {
Expand All @@ -67,11 +87,13 @@ LineFitter.prototype = {
this.sumX2 += x * x;
this.sumXY += x * y;
this.sumY += y;
if ( x < this.minx ) this.minx = x;
if ( x > this.maxx ) this.maxx = x;
},
'project': function (x) {
'f': function (x) {
var det = this.count * this.sumX2 - this.sumX * this.sumX;
var offset = (this.sumX2 * this.sumY - this.sumX * this.sumXY) / det;
var scale = (this.count * this.sumXY - this.sumX * this.sumY) / det;
return offset + x * scale;
}
};
};

0 comments on commit a31ca31

Please sign in to comment.