Skip to content

Commit f6b6fb9

Browse files
committed
release homework 3
1 parent af8f73b commit f6b6fb9

11 files changed

+380
-0
lines changed

hw3/README.md

+118
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# CS-5630 / CS-6630 Homework 3
2+
3+
_Due: Friday, September 16, 11:59 pm._
4+
5+
In this assignment, you will make interactive charts with JavaScript and D3 to explore Covid-19 data.
6+
7+
## Implementation
8+
9+
We have provided boilerplate code in [hw3.html](hw3.html) and in [script.js](script.js).
10+
11+
As in previous homeworks, add your name, your e-mail address, and your uID to the HTML elements at the top.
12+
13+
The project structure should look like this:
14+
15+
hw3/
16+
hw3.html
17+
README.md
18+
script.js
19+
data/
20+
covid_us.csv
21+
covid_utah.csv
22+
covid_ca.csv
23+
covid_ny.csv
24+
figures/
25+
26+
Remember, to be able to access the data files with JavaScript, we will need to be *serving* the homework directory, not just opening the HTML file in a browser. If your development environment doesn't provide a built-in server, start one with one of these commands:
27+
28+
$ cd path/to/hw3
29+
# for python 3
30+
$ python -m http.server 8080
31+
32+
View the page at [http://localhost:8080](http://localhost:8080)
33+
34+
## Part I: Basic Events and Setup
35+
36+
In the boilerplate HTML we provide three controls: two “Select” menus for choosing a dataset and metrics, and a “Random Subset” checkbox. Attach event listeners to the menus and checkbox in the `setup()` function, so that they would call `changeData()` when the value changes.
37+
38+
For this homework, you can add to html so that you have `<svg>` and some `<g>` elements to work with, or add those required elements in the `setup()` function, that will only be called once. The HTML also has some styling that you can use for different charts.
39+
40+
## The Data
41+
*This section is informational only, no need to implement anything.*
42+
43+
We've given you the code that loads and parses the CSV data depending on which option the user selects. `changeData()` imports the `.csv` file based on the output of menus, and output the corresponding data structure. The output is an array of objects, where the data has already been parsed:
44+
45+
```JSON
46+
[...,
47+
{cases: 5842, date: "08/27", deaths: 144},
48+
{cases: 5383, date: "08/28", deaths: 148},
49+
...]
50+
```
51+
52+
Make sure to familiarize yourself with the data structure, e.g., by printing the object and exploring it in the console.
53+
54+
Each object in the array has the date, cases, and deaths of COVID cases. `changeData()` calls `update()` with the output data, and `update()` is where the visualization will update based on the data.
55+
56+
Implement each chart with the `data` input of `update()`.
57+
58+
## Part II: Drawing the Visaulizations with D3
59+
60+
The bar chart, line chart, and area chart uses the date for x-axis, and the selected metric of the Data Metric drop-down for the values rendered on the y-axis.
61+
You can retrieve the value of the drop-down with `d3.select("#metric").node().value ;`.
62+
63+
The scatterplot uses the cases for x-axis, and the deaths for y-axis.
64+
65+
1. Construct scales for each chart. (_hint: the y-axis for bar chart, line charts, and area charts are the same_)
66+
2. Draw axis for each chart.
67+
3. Draw and update elements based on `data` input.
68+
69+
Using some constant "margin" can be helpful when placing an axis on a chart so that the axis labels are shown within the svg. We have some constants defined globally that you might find useful. But make sure that the scales are also adjusted when margins are incorporated. The scales should use `[0, maximum]` of the data visualized currently. The axes need to be transformed to the appropriate place. The scales and axes should update based on any change in the data.
70+
71+
For the bar chart and the scatterplot, use the data to populate your `rect` or `circle` elements. Position and size them correctly with the scales.
72+
73+
For the line chart and area chart, the drawing will use a single `path` element. You can add the path in your HTML or in the `setup()` function. Binding and array to a single element will be different from the bar chart and the scatterplot, `datum()` instead of `data()`.
74+
75+
Note that `datum()` called with a data structure such as an array binds the **whole** array to a single element, instead of creating multiple elements. That makes sense for a line chart, because the `path` element we'll be using for that is just one element that is re-shaped based on all of the data, as opposed to multiple bars.
76+
77+
Use `d3.line()` and `d3.area()` to generate `d` attribute for the path. We've given you (commented-out) code for the line and area constructors in `update()`.
78+
79+
We suggest to have the code for each chart in their seperate update functions, and call each chart update function in the main `update()` function. Adjust the chart update function inputs based on your need to draw the charts.
80+
81+
Your final result should look somewhat like this:
82+
83+
![Bar chart](figures/screenshot.png)
84+
85+
## Extra Credit 1: More Events
86+
87+
We focus on interactivity in this class; you will usually implement interactivity with JavaScript.
88+
We suggest using D3 events for these.
89+
90+
First, make rectangles in bar chart and points in scatter plot change color when the mouse hovers over it **using JavaScript**, not CSS hover styling. One way to do this is to make a `.hovered` class that uses a different fill. Assign elements to have the class when the mouse is on the element, and remove the class when the mouse leaves.
91+
92+
Your second interactive component will be to add an onClick listener to circles. When clicked, the browser should console log the x and y coordinates of that point to the console.
93+
94+
95+
96+
## Extra Credit 2: Transitions
97+
98+
For extra credit, animate each D3 transition (gradually change sizes, positions, and shapes when switching datasets, and fade new and old items with opacity). As we will learn later in the course, animation is _very_ attention-grabbing; make sure your animations are tasteful and subtle.
99+
100+
101+
## Demo
102+
103+
Here is a demo of how the interactions could look like. You can also check out a higher resolution version [here](figures/hw3_demo.mov).
104+
105+
![Animated Result](figures/hw3_demo.gif)
106+
107+
108+
## Grading
109+
110+
Your score on this assignment will be as follows:
111+
112+
5%: The menus trigger the appropriate functions.
113+
4 * 15%: Each chart is rendered properly on page load (15% for each chart)
114+
15% The charts, including the axis update based on data change.
115+
10%: Elements are removed when "Random Subset" loads a smaller dataset.
116+
10%: Elements are created and styled appropriately when "Random Subset" loads a larger dataset.
117+
5%: Extra Credit 1: Elements change styles on hover and console log the data points on click.
118+
5%: Extra Credit 2: All D3 transitions are animated **tastefully**.

hw3/data/covid_ca.csv

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
date,cases,deaths27-Aug,5842,14428-Aug,5383,14829-Aug,2670,6630-Aug,3134,1931-Aug,8197,971-Sep,4582,1502-Sep,4907,1673-Sep,4864,1554-Sep,4622,1555-Sep,2497,306-Sep,3379,387-Sep,2348,428-Sep,4954,819-Sep,3484,15310-Sep,2474,73

hw3/data/covid_ny.csv

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
date,cases,deaths27-Aug,770,528-Aug,625,829-Aug,645,630-Aug,704,1131-Aug,651,61-Sep,746,92-Sep,696,63-Sep,867,44-Sep,851,65-Sep,788,56-Sep,724,77-Sep,519,88-Sep,597,209-Sep,576,010-Sep,739,1

hw3/data/covid_us.csv

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
date,cases,deaths27-Aug,46184,111828-Aug,50564,103529-Aug,43274,116430-Aug,34834,42731-Aug,37428,4951-Sep,42477,10782-Sep,40683,11483-Sep,45995,10694-Sep,49629,9605-Sep,43062,7496-Sep,23468,5107-Sep,26074,2598-Sep,25766,4879-Sep,35886,125210-Sep,36554,1066

hw3/data/covid_utah.csv

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
date,cases,deaths27-Aug,383,228-Aug,390,429-Aug,459,030-Aug,448,031-Aug,253,01-Sep,296,22-Sep,417,13-Sep,506,44-Sep,513,55-Sep,433,16-Sep,388,27-Sep,373,18-Sep,326,19-Sep,314,310-Sep,346,3

hw3/figures/hw3_demo.gif

926 KB
Loading

hw3/figures/hw3_demo.mov

3.17 MB
Binary file not shown.

hw3/figures/screenshot.png

66.6 KB
Loading

hw3/figures/staircase.png

2.88 KB
Loading

hw3/hw3.html

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8" />
6+
<title>Homework 3</title>
7+
<style>
8+
/* style div and headers */
9+
.chart,
10+
h2 {
11+
text-align: center;
12+
}
13+
14+
.row {
15+
display: flex;
16+
flex-wrap: wrap;
17+
}
18+
19+
.toolbox span {
20+
padding: 5px;
21+
}
22+
23+
svg {
24+
padding: 10px;
25+
width: 500px;
26+
height: 250px;
27+
}
28+
29+
/* style of bar charts */
30+
.bar-chart rect {
31+
fill: rgb(79, 175, 211);
32+
}
33+
34+
.bar-chart .hovered {
35+
fill: #979696;
36+
}
37+
38+
/* style of line charts */
39+
.line-chart {
40+
stroke: rgb(79, 175, 211);
41+
stroke-width: 2;
42+
fill: none;
43+
}
44+
45+
text {
46+
fill: black;
47+
}
48+
49+
/* style of area charts */
50+
.area-chart {
51+
fill: rgb(79, 175, 211);
52+
}
53+
54+
/* style of scatter plot */
55+
.scatter-plot circle {
56+
fill: rgb(79, 175, 211);
57+
}
58+
59+
.scatter-plot .hovered {
60+
fill: #979696;
61+
}
62+
</style>
63+
<!-- d3 script -->
64+
<script src="https://d3js.org/d3.v7.min.js"></script>
65+
</head>
66+
67+
<body>
68+
<h3>CS-5630 / CS-6630 Homework 3</h3>
69+
<address>
70+
<span>Your Name</span>
71+
<span>Your Email</span>
72+
<span>Your UID</span>
73+
</address>
74+
<br />
75+
<hr />
76+
<br />
77+
78+
<div class="toolbox">
79+
80+
<span>
81+
<label>Dataset:</label>
82+
<select id="dataset">
83+
<option value="covid_us">The US</option>
84+
<option selected value="covid_utah">Utah</option>
85+
<option value="covid_ca">California</option>
86+
<option value="covid_ny">New York</option>
87+
</select>
88+
</span>
89+
<span>
90+
<label>Data Metric</label>
91+
<select id="metric">
92+
<option value="deaths">Deaths</option>
93+
<option value="cases">Cases</option>
94+
</select>
95+
</span>
96+
97+
<span> <input type="checkbox" id="random" /> Random Subset </span>
98+
</div>
99+
<br />
100+
101+
<div class="row chart">
102+
<div class="chart">
103+
<h2>Bar Charts</h2>
104+
<div id="Barchart-div">
105+
</div>
106+
</div>
107+
108+
<div class="chart">
109+
<h2>Line Charts</h2>
110+
<div id="Linechart-div"></div>
111+
</div>
112+
</div>
113+
114+
<div class="row chart">
115+
<div class="chart">
116+
<h2>Area Charts</h2>
117+
<div id="Areachart-div"></div>
118+
</div>
119+
120+
<div class="chart">
121+
<h2>Scatterplot</h2>
122+
<div id="Scatterplot-div"></div>
123+
</div>
124+
</div>
125+
</body>
126+
<script src="script.js"></script>
127+
128+
</html>

hw3/script.js

+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// Constants for the charts, that would be useful.
2+
const CHART_WIDTH = 500;
3+
const CHART_HEIGHT = 250;
4+
const MARGIN = { left: 50, bottom: 20, top: 20, right: 20 };
5+
const ANIMATION_DUATION = 300;
6+
7+
setup();
8+
9+
function setup () {
10+
11+
// Fill in some d3 setting up here if you need
12+
// for example, svg for each chart, g for axis and shapes
13+
14+
changeData();
15+
}
16+
17+
/**
18+
* Render the visualizations
19+
* @param data
20+
*/
21+
function update (data) {
22+
23+
// ****** TODO ******
24+
25+
26+
// Syntax for line generator.
27+
// when updating the path for line chart, use the function as the input for 'd' attribute.
28+
// https://github.com/d3/d3-shape/blob/main/README.md
29+
30+
31+
// const lineGenerator = d3.line()
32+
// .x(d => the x coordinate for a point of the line)
33+
// .y(d => the y coordinate for a point of the line);
34+
35+
// Syntax for area generator.
36+
// the area is bounded by upper and lower lines. So you can specify x0, x1, y0, y1 seperately. Here, since the area chart will have upper and lower sharing the x coordinates, we can just use x().
37+
// Similarly, use the function as the input for 'd' attribute.
38+
39+
// const areaGenerator = d3.area()
40+
// .x(d => the x coordinates for upper and lower lines, both x0 and x1)
41+
// .y1(d => the y coordinate for the upper line)
42+
// .y0(d=> the base line y coordinate for the area);
43+
44+
45+
//Set up scatter plot x and y axis.
46+
//Since we are mapping death and case, we need new scales instead of the ones above.
47+
//Cases would be the horizontal axis, so we need to use width related constants.
48+
//Deaths would be vertical axis, so that would need to use height related constants.
49+
50+
51+
//TODO
52+
// call each update function below, adjust the input for the functions if you need to.
53+
}
54+
55+
/**
56+
* Update the bar chart
57+
*/
58+
59+
function updateBarChart () {
60+
61+
}
62+
63+
/**
64+
* Update the line chart
65+
*/
66+
function updateLineChart () {
67+
68+
}
69+
70+
/**
71+
* Update the area chart
72+
*/
73+
function updateAreaChart () {
74+
75+
}
76+
77+
/**
78+
*/
79+
80+
function updateScatterPlot () {
81+
82+
}
83+
84+
85+
/**
86+
* Update the data according to document settings
87+
*/
88+
function changeData () {
89+
// Load the file indicated by the select menu
90+
const dataFile = d3.select('#dataset').property('value');
91+
92+
d3.csv(`data/${dataFile}.csv`)
93+
.then(dataOutput => {
94+
95+
/**
96+
* D3 loads all CSV data as strings. While Javascript is pretty smart
97+
* about interpreting strings as numbers when you do things like
98+
* multiplication, it will still treat them as strings where it makes
99+
* sense (e.g. adding strings will concatenate them, not add the values
100+
* together, or comparing strings will do string comparison, not numeric
101+
* comparison).
102+
*
103+
* We need to explicitly convert values to numbers so that comparisons work
104+
* when we call d3.max()
105+
**/
106+
107+
const dataResult = dataOutput.map((d) => ({
108+
cases: parseInt(d.cases),
109+
deaths: parseInt(d.deaths),
110+
date: d3.timeFormat("%m/%d")(d3.timeParse("%d-%b")(d.date))
111+
}));
112+
if (document.getElementById('random').checked) {
113+
// if random subset is selected
114+
update(randomSubset(dataResult));
115+
} else {
116+
update(dataResult);
117+
}
118+
}).catch(e => {
119+
console.log(e);
120+
alert('Error!');
121+
});
122+
}
123+
124+
/**
125+
* Slice out a random chunk of the provided in data
126+
* @param data
127+
*/
128+
function randomSubset (data) {
129+
return data.filter((d) => Math.random() > 0.5);
130+
}

0 commit comments

Comments
 (0)