83 lines
2.7 KiB
JavaScript
83 lines
2.7 KiB
JavaScript
// create empty chart SVGs - pyramid charts start with a centered group
|
|
const dollarsG = makeChart("#pyramidDollars", 200)
|
|
.append("g")
|
|
.attr("transform", `translate(${chartWidth / 2}, ${margin.top})`);
|
|
const percentG = makeChart("#pyramidPercent", 200)
|
|
.append("g")
|
|
.attr("transform", `translate(${chartWidth / 2}, ${margin.top})`);
|
|
const lineDollars = makeChart("#lineChartDollars", 400);
|
|
const linePercent = makeChart("#lineChartPercent", 400);
|
|
|
|
// global state
|
|
let levelsData = []; // placeholder of data to be loaded
|
|
let yearIndex = 0; // currently displayed year index
|
|
let timerFunc = null; // handle to timer function if animating
|
|
|
|
// called every frame of animation -- draw all charts
|
|
// actual functions to draw charts are in other JS files (pyramid/linechart.js)
|
|
function updateCharts() {
|
|
drawPyramid(dollarsG, yearIndex, "dollars");
|
|
drawPyramid(percentG, yearIndex, "percent");
|
|
drawLineChart(lineDollars, levelsData, "dollars");
|
|
drawLineChart(linePercent, levelsData, "percent");
|
|
}
|
|
|
|
// disable timer (see below setInterval code)
|
|
function stopTimer() {
|
|
clearInterval(timerFunc);
|
|
timerFunc = null;
|
|
d3.select("#playPause").text("Play");
|
|
}
|
|
|
|
// The below global code runs on page load to set up the application.
|
|
|
|
// color the text in the paragraph to act as a key
|
|
d3.selectAll(".pyramidLabel").style("color", (d, i) => d3.schemeOranges[5][i]);
|
|
|
|
// load CSV and parse data -- then draw charts for first time
|
|
d3.csv("levels.csv").then((data) => {
|
|
levelsData = data;
|
|
updateCharts();
|
|
});
|
|
|
|
// if they drag the slider, update charts
|
|
d3.select("#timeSlider").on("change", function (e) {
|
|
// update the index & redraw
|
|
yearIndex = e.target.value;
|
|
updateCharts();
|
|
});
|
|
|
|
// if play button is clicked toggle play state
|
|
d3.select("#playPause").on("click", function (e) {
|
|
// toggle the playing class -- used for display
|
|
// as well as knowing if the animation is active
|
|
e.target.classList.toggle("playing");
|
|
|
|
// if the state is now playing -- start a timer function
|
|
if (e.target.classList.contains("playing")) {
|
|
// toggle button to say 'Pause'
|
|
d3.select(e.target).text("Pause");
|
|
|
|
// reset timer if they've gone past the end
|
|
if (yearIndex >= levelsData.length) {
|
|
yearIndex = 0;
|
|
}
|
|
|
|
// setInterval will call this function every 100ms until cancelled
|
|
// the variable "timerFunc" stores a reference to the timer so we can
|
|
// pause/cancel it
|
|
timerFunc = setInterval(function () {
|
|
yearIndex += 1;
|
|
const timeSlider = d3.select("#timeSlider");
|
|
if (yearIndex >= levelsData.length && timerFunc) {
|
|
stopTimer();
|
|
yearIndex = levelsData.length - 1;
|
|
}
|
|
timeSlider.attr("value", yearIndex);
|
|
updateCharts();
|
|
}, 100);
|
|
} else if (timerFunc) {
|
|
stopTimer();
|
|
}
|
|
});
|