Declare commits. It is an array of all the values of the third column in dataset, which is the contributions. Then set the data property of the object in the series array, to commits.
function renderLineChart()
{
var rngYearFrom = document.getElementById("rngYearFrom");
var rngYearTo = document.getElementById("rngYearTo");
var yearFrom = parseInt(rngYearFrom.value);
var yearTo = parseInt(rngYearTo.value);
var dataset = currentData.filter((x) =>{ return parseInt(x[0]) >= yearFrom && parseInt(x[0]) <= yearTo});
var years = dataset.map(col => monthToName(col[1]) + " " + col[0]);
var commits = dataset.map(col => col[2]);
var series = [];
series = [
{
name: "commits",
type: "spline",
data: commits,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
];
}
{
var rngYearFrom = document.getElementById("rngYearFrom");
var rngYearTo = document.getElementById("rngYearTo");
var yearFrom = parseInt(rngYearFrom.value);
var yearTo = parseInt(rngYearTo.value);
var dataset = currentData.filter((x) =>{ return parseInt(x[0]) >= yearFrom && parseInt(x[0]) <= yearTo});
var years = dataset.map(col => monthToName(col[1]) + " " + col[0]);
var commits = dataset.map(col => col[2]);
var series = [];
series = [
{
name: "commits",
type: "spline",
data: commits,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
];
}
Run this! You should see right now that both range sliders are at the minimum value, 2016.
Change the values. The chart should refresh!
Increase the range. See what happens?
We've created a line chart. But sometimes, we want comparisons. Like, How does the Line chart for 2021 compare to 2022?
That's what the checkbox is for. Remember this guy? Well, make sure it runs renderLineChart() when clicked.
<label for="rngYearFrom"><input type="checkbox" id="cbSeparateYears" onclick="renderLineChart()"> SEPARATE YEARS</label>
And in the code that runs when DOM is loaded, we want to populate yearSeriesData because we're going to use it. Right after defining yearMin and yearMax, we make sure yearSeriesData has index pointers corresponding to those years. And the value for each element is another array of all the elements in currentData where the first column (index 0, year) corresponds to the current year being referenced, i.
document.addEventListener("DOMContentLoaded", function () {
fetch("http://www.teochewthunder.com/demo/hc_github/hcdata_github.csv")
.then(response => response.text())
.then(csvData => {
const rows = csvData.split("\n");
currentData = rows.slice(1).map(row => {
const cols = row.split(",");
var year = parseInt(cols[0]);
var month = parseInt(cols[1]);
var contributions = parseInt(cols[2]);
return [year, month, contributions];
});
var years = currentData.map(col => col[0]);
var yearMin = Math.min(...years);
var yearMax = Math.max(...years);
for (var i = yearMin; i <= yearMax; i++)
{
yearSeriesData[i] = currentData.filter((x) => { return x[0] == i; });
}
var yearFrom = yearMin;
var yearTo = yearMin;
var rngYearFrom = document.getElementById("rngYearFrom");
var rngYearTo = document.getElementById("rngYearTo");
var opYearFrom = document.getElementById("opYearFrom");
var opYearTo = document.getElementById("opYearTo");
rngYearFrom.min = yearMin;
rngYearFrom.max = yearMax;
rngYearFrom.value = yearFrom;
opYearFrom.value = yearFrom;
rngYearTo.min = yearMin;
rngYearTo.max = yearMax;
rngYearTo.value = yearTo;
opYearTo.value = yearTo;
renderLineChart();
});
});
fetch("http://www.teochewthunder.com/demo/hc_github/hcdata_github.csv")
.then(response => response.text())
.then(csvData => {
const rows = csvData.split("\n");
currentData = rows.slice(1).map(row => {
const cols = row.split(",");
var year = parseInt(cols[0]);
var month = parseInt(cols[1]);
var contributions = parseInt(cols[2]);
return [year, month, contributions];
});
var years = currentData.map(col => col[0]);
var yearMin = Math.min(...years);
var yearMax = Math.max(...years);
for (var i = yearMin; i <= yearMax; i++)
{
yearSeriesData[i] = currentData.filter((x) => { return x[0] == i; });
}
var yearFrom = yearMin;
var yearTo = yearMin;
var rngYearFrom = document.getElementById("rngYearFrom");
var rngYearTo = document.getElementById("rngYearTo");
var opYearFrom = document.getElementById("opYearFrom");
var opYearTo = document.getElementById("opYearTo");
rngYearFrom.min = yearMin;
rngYearFrom.max = yearMax;
rngYearFrom.value = yearFrom;
opYearFrom.value = yearFrom;
rngYearTo.min = yearMin;
rngYearTo.max = yearMax;
rngYearTo.value = yearTo;
opYearTo.value = yearTo;
renderLineChart();
});
});
Next we have renderLineChart(). Grab cbSeparateYears as the checkbox, then implement a conditional block that checks if cbSeparateYears is checked. If not, define series the way we did previously.
function renderLineChart()
{
var rngYearFrom = document.getElementById("rngYearFrom");
var rngYearTo = document.getElementById("rngYearTo");
var cbSeparateYears = document.getElementById("cbSeparateYears");
var yearFrom = parseInt(rngYearFrom.value);
var yearTo = parseInt(rngYearTo.value);
var dataset = currentData.filter((x) =>{ return parseInt(x[0]) >= yearFrom && parseInt(x[0]) <= yearTo});
var years = dataset.map(col => monthToName(col[1]) + " " + col[0]);
var commits = dataset.map(col => col[2]);
var series = [];
if (cbSeparateYears.checked)
{
}
else
{
series = [
{
name: "commits",
type: "spline",
data: commits,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
];
}
const chart = Highcharts.chart("container", {
chart:
{
borderColor: "rgba(250, 100, 0, 1)",
borderRadius: 10,
borderWidth: 2,
},
title:
{
text: "My Contributions",
style: { "color": "rgba(250, 100, 0, 1)", "font-size": "2.5em", "font-weight": "bold" }
},
subtitle:
{
text: "GitHub statistics by TeochewThunder",
style: { "color": "rgba(250, 100, 0, 0.8)", "font-size": "0.8em" }
},
xAxis:
{
categories: years
},
yAxis:
{
title:
{
text: "Commits"
},
gridLineColor: "rgba(250, 100, 0, 0.2)",
tickColor: "rgba(250, 100, 0, 0.2)"
},
series: series
});
}
{
var rngYearFrom = document.getElementById("rngYearFrom");
var rngYearTo = document.getElementById("rngYearTo");
var cbSeparateYears = document.getElementById("cbSeparateYears");
var yearFrom = parseInt(rngYearFrom.value);
var yearTo = parseInt(rngYearTo.value);
var dataset = currentData.filter((x) =>{ return parseInt(x[0]) >= yearFrom && parseInt(x[0]) <= yearTo});
var years = dataset.map(col => monthToName(col[1]) + " " + col[0]);
var commits = dataset.map(col => col[2]);
var series = [];
if (cbSeparateYears.checked)
{
}
else
{
series = [
{
name: "commits",
type: "spline",
data: commits,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
];
}
const chart = Highcharts.chart("container", {
chart:
{
borderColor: "rgba(250, 100, 0, 1)",
borderRadius: 10,
borderWidth: 2,
},
title:
{
text: "My Contributions",
style: { "color": "rgba(250, 100, 0, 1)", "font-size": "2.5em", "font-weight": "bold" }
},
subtitle:
{
text: "GitHub statistics by TeochewThunder",
style: { "color": "rgba(250, 100, 0, 0.8)", "font-size": "0.8em" }
},
xAxis:
{
categories: years
},
yAxis:
{
title:
{
text: "Commits"
},
gridLineColor: "rgba(250, 100, 0, 0.2)",
tickColor: "rgba(250, 100, 0, 0.2)"
},
series: series
});
}
If cbSeparateYears is checked, we'll populate series with more elements than just one. We will use a For loop to go from yearFrom to yearTo, then extract the relevant year's data into an object, seriesData. Then we will push an object containing i and seriesData, into series.
var series = [];
if (cbSeparateYears.checked)
{
for (var i = yearFrom; i <= yearTo; i++)
{
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
else
{
series = [
{
name: "commits",
type: "spline",
data: commits,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
];
}
if (cbSeparateYears.checked)
{
for (var i = yearFrom; i <= yearTo; i++)
{
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
else
{
series = [
{
name: "commits",
type: "spline",
data: commits,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
];
}
Just above, we change years. If cbSeparateYears is checked, this means that we are displaying multiple years on separate lines, so it wouldn't make sense to display both month and year on the x-axis any more. So in that case, we'll omit the year.
var dataset = currentData.filter((x) =>{ return parseInt(x[0]) >= yearFrom && parseInt(x[0]) <= yearTo});
var years = dataset.map(col => monthToName(col[1]) + (cbSeparateYears.checked ? "" : " " + col[0]));
var commits = dataset.map(col => col[2]);
var series = [];
if (cbSeparateYears.checked)
{
var years = dataset.map(col => monthToName(col[1]) + (cbSeparateYears.checked ? "" : " " + col[0]));
var commits = dataset.map(col => col[2]);
var series = [];
if (cbSeparateYears.checked)
{
See? We have multiple lines when we track from 2016 to 2019... but it looks like spaghetti.
What we can do here is mitigate it by making them different shades of orange. We could make them different colors altogether, of course. But just for arguments sake, let's do orange. First, we define diff as the gap in years between yearTo and yearFrom. Because we'll be dividing by this number, add 1 so we don't get a Divide-By_Zero error.
if (cbSeparateYears.checked)
{
for (var i = yearFrom; i <= yearTo; i++)
{
var diff = (yearTo - yearFrom + 1);
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
{
for (var i = yearFrom; i <= yearTo; i++)
{
var diff = (yearTo - yearFrom + 1);
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
Now define r and g. r will always be greater than g if we're doing shades of orange. The formula here makes sure that the final results of r and g commensurate with the value of i, no matter how small.
if (cbSeparateYears.checked)
{
for (var i = yearFrom; i <= yearTo; i++)
{
var diff = (yearTo - yearFrom + 1);
var r = (250 / diff) * (1 + i - yearFrom);
var g = (100 / diff) * (1 + i - yearFrom);
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
{
for (var i = yearFrom; i <= yearTo; i++)
{
var diff = (yearTo - yearFrom + 1);
var r = (250 / diff) * (1 + i - yearFrom);
var g = (100 / diff) * (1 + i - yearFrom);
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(250, 100, 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
Then we ensure that r and g are part of the formula that defines lineColor.
if (cbSeparateYears.checked)
{
for (var i = yearFrom; i <= yearTo; i++)
{
var diff = (yearTo - yearFrom + 1);
var r = (250 / diff) * (1 + i - yearFrom);
var g = (100 / diff) * (1 + i - yearFrom);
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(" + r + ", " + g + ", 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
{
for (var i = yearFrom; i <= yearTo; i++)
{
var diff = (yearTo - yearFrom + 1);
var r = (250 / diff) * (1 + i - yearFrom);
var g = (100 / diff) * (1 + i - yearFrom);
var seriesData = yearSeriesData[i].map(col => col[2]);
series.push(
{
name: i,
type: "spline",
data: seriesData,
lineColor: "rgba(" + r + ", " + g + ", 0, 1)",
lineWidth: 5,
dashStyle: "Solid",
marker:
{
fillColor: "none"
}
}
);
}
}
Note: This works only if there aren't too many colors. Right now I'm just representing a handful, so color differences are distinct enough.
Go on, have fun with it. Adjust the years, check and uncheck the checkbox. See what these get you.
Stay committed,
T___T
T___T





No comments:
Post a Comment