Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feedback #1

Open
wants to merge 4 commits into
base: feedback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions answers/index.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css"> <!-- Link to the external CSS file -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,700&display=swap">
<title>D3 Bar Chart - 311 Calls in Boston</title>
<link rel="stylesheet" href="styles.css"> <!-- Link to the external CSS file -->
<link rel="stylesheet" href="style.css"> <!-- Link to the external CSS file -->
</head>
<body>
<header>
<h1>311 Calls in Boston in 2023</h1>
<p>Broken down by the top 10 types</p>
<div id="chart_311" class="chart"></div>

</header>
<div id="chart" class="chart"></div>
<!-- Your chart will be appended here -->

<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="script.js"></script>
</body>
Expand Down
249 changes: 181 additions & 68 deletions answers/script.js
Original file line number Diff line number Diff line change
@@ -1,70 +1,183 @@
// Load CSV data
d3.csv('311_boston_data.csv').then(data => {
// Process the data
data.forEach(d => {
d.Count = +d.Count; // Convert Count to a number
// Set dimensions with increased right margin for labels
const margin = {top: 80, right: 150, bottom: 80, left: 250};
const width = 1200 - margin.left - margin.right;
let height = 800 - margin.top - margin.bottom;

// Create SVG container with a wrapper div
d3.select("#chart")
.append("div")
.style("position", "relative");

// Create SVG
const svg = d3.select("#chart div")
.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);

// Create static data array from CSV content
const fullData = [
{reason: "Enforcement & Abandoned Vehicles", Count: 61541},
{reason: "Sanitation", Count: 59389},
{reason: "Street Cleaning", Count: 45659},
{reason: "Code Enforcement", Count: 31812},
{reason: "Highway Maintenance", Count: 25096},
{reason: "Signs & Signals", Count: 11209},
{reason: "Trees", Count: 10390},
{reason: "Recycling", Count: 9955},
{reason: "Street Lights", Count: 8499},
{reason: "Park Maintenance & Safety", Count: 7932},
{reason: "Housing", Count: 7590},
{reason: "Needle Program", Count: 7413},
{reason: "Building", Count: 5209},
{reason: "Environmental Services", Count: 4416},
{reason: "Animal Issues", Count: 4155},
{reason: "Employee & General Comments", Count: 2166},
{reason: "Administrative & General Requests", Count: 2025},
{reason: "Graffiti", Count: 1839},
{reason: "Health", Count: 1349},
{reason: "Abandoned Bicycle", Count: 1318},
{reason: "Noise Disturbance", Count: 832},
{reason: "Traffic Management & Engineering", Count: 751},
{reason: "Catchbasin", Count: 621},
{reason: "Notification", Count: 607},
{reason: "Sidewalk Cover / Manhole", Count: 291},
{reason: "Operations", Count: 283},
{reason: "Fire Hydrant", Count: 205},
{reason: "General Request", Count: 196},
{reason: "Generic Noise Disturbance", Count: 109},
{reason: "Pothole", Count: 85},
{reason: "Boston Bikes", Count: 64},
{reason: "Weights and Measures", Count: 52},
{reason: "Air Pollution Control", Count: 35},
{reason: "Cemetery", Count: 29},
{reason: "Neighborhood Services Issues", Count: 28},
{reason: "Parking Complaints", Count: 19},
{reason: "Office of The Parking Clerk", Count: 18},
{reason: "Bridge Maintenance", Count: 8},
{reason: "Massport", Count: 8},
{reason: "Valet", Count: 7},
{reason: "Billing", Count: 6},
{reason: "Programs", Count: 6},
{reason: "Alert Boston", Count: 3},
{reason: "MBTA", Count: 1}
].sort((a, b) => b.Count - a.Count);

let currentData = fullData.slice(0, 10);
let isShowingAll = false;

// Create scales
const y = d3.scaleBand()
.padding(0.1);

const x = d3.scaleLinear();

// Function to update chart
function updateChart(data) {
height = data.length * 40;

y.range([0, height])
.domain(data.map(d => d.reason));

x.range([0, width])
.domain([0, d3.max(data, d => d.Count)]);

d3.select("#chart div svg")
.attr("height", height + margin.top + margin.bottom);

const bars = svg.selectAll(".bar")
.data(data);

bars.exit().remove();

const newBars = bars.enter()
.append("rect")
.attr("class", "bar");

bars.merge(newBars)
.transition()
.duration(750)
.attr("y", d => y(d.reason))
.attr("height", y.bandwidth())
.attr("x", 0)
.attr("width", d => x(d.Count))
.style("fill", "gray");

svg.selectAll(".x-axis").remove();
svg.selectAll(".y-axis").remove();

svg.append("g")
.attr("class", "x-axis")
.call(d3.axisTop(x)
.tickFormat(d3.format(",d")));

svg.append("g")
.attr("class", "y-axis")
.call(d3.axisLeft(y));

const labels = svg.selectAll(".label")
.data(data);

labels.exit().remove();

const newLabels = labels.enter()
.append("text")
.attr("class", "label");

labels.merge(newLabels)
.transition()
.duration(750)
.attr("y", d => y(d.reason) + y.bandwidth() / 2)
.attr("x", d => x(d.Count) + 10)
.attr("dy", ".35em")
.style("font-size", "12px")
.text(d => d3.format(",")(d.Count));

// Update footnote position
svg.select(".footnote")
.attr("y", height + 60);
}

// Add toggle button
d3.select("#chart div")
.append("button")
.attr("class", "toggle-button")
.style("position", "absolute")
.style("top", "10px")
.style("right", "10px")
.text("Show All Results")
.on("click", function() {
isShowingAll = !isShowingAll;
this.textContent = isShowingAll ? "Show Top 10" : "Show All Results";
updateChart(isShowingAll ? fullData : fullData.slice(0, 10));
});

// Sort the data by Count in descending order. first step to top 10
data.sort((a, b) => b.Count - a.Count);

// Take only the top 10 types
const top10Data = data.slice(0, 10);

// Set up SVG container
const svgWidth = 800;
const svgHeight = 500;
const margin = { top: 40, right: 40, bottom: 80, left: 200 };
const width = svgWidth - margin.left - margin.right;
const height = svgHeight - margin.top - margin.bottom;

const svg = d3.select('#chart_311')
.append('svg')
.attr('width', svgWidth)
.attr('height', svgHeight)
.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);

// Create scales
const yScale = d3.scaleBand()
.domain(top10Data.map(d => d.reason))
.range([0, height])
.padding(0.2);

const xScale = d3.scaleLinear()
.domain([0, d3.max(top10Data, d => d.Count)])
.range([0, width]);

// Create bars
svg.selectAll('rect')
.data(top10Data)
.enter()
.append('rect')
.attr('x', 0)
.attr('y', d => yScale(d.reason))
.attr('width', d => xScale(d.Count))
.attr('height', yScale.bandwidth())
.attr('fill', 'blue')
.on('mouseover', function (event, d) {
d3.select(this).attr('fill', 'orange'); // Change color on hover
})
.on('mouseout', function () {
d3.select(this).attr('fill', 'blue'); // Revert color on mouseout
});

// Add axes
svg.append('g')
.call(d3.axisLeft(yScale));

svg.append('g')
.attr('transform', `translate(0,${height})`)
.call(d3.axisBottom(xScale));

// Add attribution line at the bottom
svg.append('text')
.attr('x', width / 2)
.attr('y', height + margin.top + 20) // Adjust the y-coordinate for proper placement
.attr('text-anchor', 'left')
.style('font-size', '12px')
.text('Chart created by Aarushi Sahejpal. Data source: Boston.gov');
});
// Initial render
updateChart(currentData);

// Add title
svg.append("text")
.attr("class", "chart-title")
.attr("x", width / 2)
.attr("y", -60)
.style("text-anchor", "middle")
.style("font-size", "16px")


// Add X axis label
svg.append("text")
.attr("class", "axis-label")
.attr("x", width / 2)
.attr("y", -margin.top/1.5)
.style("text-anchor", "middle")
.text("Number of Calls");

// Add citation and authorship footnote
svg.append("text")
.attr("class", "footnote")
.attr("x", 0)
.attr("y", height + 60)
.style("font-size", "12px")
.style("fill", "gray")
.text("Data Source: Boston 311 Service Requests (2023) | Chart by Livi & Perplexity AI | Updated: Wednesday, January 15, 2025, 4 PM EST");
47 changes: 47 additions & 0 deletions answers/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#chart {
margin: 20px;
width: 100%;
overflow: visible;
}

.bar {
fill: gray;
transition: fill 0.3s ease;
}

.bar:hover {
fill: darkgray;
}

.axis-text {
font-size: 12px;
font-family: Arial, sans-serif;
}

.chart-title {
font-size: 16px;
font-family: Arial, sans-serif;
}

.toggle-button {
padding: 10px 20px;
background-color: gray;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 14px;
transition: background-color 0.3s ease;
}

.toggle-button:hover {
background-color: darkgray;
}

.label {
font-family: Arial, sans-serif;
}

.footnote {
font-family: Arial, sans-serif;
}
49 changes: 16 additions & 33 deletions answers/styles.css
Original file line number Diff line number Diff line change
@@ -1,45 +1,28 @@
/* Add any CSS styles here */
body {
font-family: 'Roboto', sans-serif; /* Use Roboto font */
background-color: whitesmoke;
color: black;
#chart {
margin: 20px;
}

header {
text-align: left;
margin-bottom: 10px; /* Adjust margin as needed for the header */
.bar {
fill: skyblue;
transition: fill 0.3s ease;
}

svg {
margin-top: 10px; /* Adjust margin as needed for the chart */
}s

h1 {
color: black;
font-size: 2em; /* Increase font size for the main header */
margin-bottom: 0; /* No margin at the bottom of the main header */
transition: color 0.3s; /* Smooth transition for color change on hover */
.bar:hover {
fill: steelblue;
}

p {
line-height: 1.5;
font-size: 1.2em; /* Increase font size for the subheader */
margin-top: 0; /* sNo margin at the top of the subheader */
margin-bottom: 20px; /* Adjust margin as needed for the subheader */
font-weight: bold;
transition: color 0.3s; /* Smooth transition for color change on hover */
.axis-label {
font-size: 12px;
font-family: Arial, sans-serif;
}

/* Hover styles */
h1:hover,
p:hover {
color: #007bff; /* Change the color on hover */
.chart-title {
font-size: 16px;
font-family: Arial, sans-serif;
text-anchor: middle;
}

#attribution {
text-align: center;
position: absolute;
bottom: 10px;
width: 100%;
.axis-text {
font-family: Arial, sans-serif;
font-size: 12px;
}
Loading