Skip to content

Instantly share code, notes, and snippets.

@karthiir
Created March 19, 2017 21:09
Show Gist options
  • Save karthiir/bc3bac024fd215dbc5687fbdffc8bf6a to your computer and use it in GitHub Desktop.
Save karthiir/bc3bac024fd215dbc5687fbdffc8bf6a to your computer and use it in GitHub Desktop.
Final Project
license: mit
[{
"campus": "Chico",
"gap": [
[2000, 18],
[2001, 13],
[2002, 15],
[2003, 8],
[2004, 11],
[2005, 14],
[2006, 13],
[2007, 16]
],
"gradrate": [
[2000, 54],
[2001, 52],
[2002, 56],
[2003, 58],
[2004, 62],
[2005, 59],
[2006, 57],
[2007, 56]
],
"pell": [
[2000, 21],
[2001, 23],
[2002, 23],
[2003, 25],
[2004, 20],
[2005, 20],
[2006, 21],
[2007, 21]
],
"total": [
[2000, 1931],
[2001, 2092],
[2002, 1995],
[2003, 1970],
[2004,2198],
[2005, 2300],
[2006, 2430],
[2007, 2710]
]
}, {
"campus": "Dominguez Hills",
"gap": [
[2000, -6],
[2001, 1],
[2002, -5],
[2003, -3],
[2004, -2],
[2005, 2],
[2006, 4],
[2007, 10]
],
"gradrate": [
[2000, 33],
[2001, 28],
[2002, 34],
[2003, 35],
[2004, 31],
[2005, 24],
[2006, 28],
[2007, 29]
],
"pell": [
[2000, 71],
[2001, 73],
[2002, 69],
[2003, 71],
[2004, 66],
[2005, 62],
[2006, 61],
[2007, 61]
],
"total": [
[2000, 495],
[2001, 561],
[2002, 630],
[2003, 639],
[2004,673],
[2005, 705],
[2006, 984],
[2007, 913]
]
}, {
"campus": "East Bay",
"gap": [
[2000, 7],
[2001, 8],
[2002, 18],
[2003, 9],
[2004, 9],
[2005,14],
[2006,22],
[2007, 17]
],
"gradrate": [
[2000, 43],
[2001, 40],
[2002, 44],
[2003, 48],
[2004, 45],
[2005, 43],
[2006, 41],
[2007, 48]
],
"pell": [
[2000, 33],
[2001, 43],
[2002, 36],
[2003, 37],
[2004, 35],
[2005, 33],
[2006, 37],
[2007, 37]
],
"total": [
[2000, 669],
[2001, 692],
[2002, 746],
[2003, 672],
[2004,840],
[2005, 686],
[2006, 881],
[2007, 1032]
]
}]
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<title>The Wealth & Health of data</title>
<style>
html {
text-align: center;
}
body {
padding: 0 20px 20px 20px;
background: #fcfcfa;
color: #333;
font-family: Gotham, "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 1em auto 4em auto;
position: relative;
}
h1 {
text-align: left;
font-weight: normal;
font-size: 22px;
}
#chart {
width: 960px;
height: 406px;
margin-left: -40px;
}
.label{
font: 14pt sans-serif;
}
text {
font: 11px sans-serif;
}
.dot {
fill-opacity: .7;
transition: opacity 0.3s;
}
.dot:hover {
fill-opacity: 1;
transition: opacity 0.3s;
}
.active {
fill-opacity: 1;
stroke-width: 1;
stroke-opacity: 1;
}
.legend {
opacity: .7;
transition: opacity 0.3s;
}
.axis path {
display: none;
}
.axis line {
stroke-width:1px;
stroke: #ccc;
stroke-dasharray: 2px 2px;
}
.label {
fill: #666;
}
.year.label {
font: 500 100px "Helvetica Neue";
fill: #ddd;
}
.year.label.active {
fill: #aaa;
}
.overlay {
fill: none;
pointer-events: all;
cursor: ew-resize;
}
input[type=range] {
-webkit-appearance: none;
margin: 10px 0;
width: 100%;
}
input[type=range]:focus {
outline: none;
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 10px;
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
background: #ddd;
border-radius: 25px;
border: 0px solid #000101;
}
input[type=range]::-webkit-slider-thumb {
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
border: 0px solid #000000;
height: 20px;
width: 20px;
border-radius: 7px;
background: #337ab7;
cursor: pointer;
-webkit-appearance: none;
margin-top: -4.6px;
}
input[type=range]:focus::-webkit-slider-runnable-track {
background: #ddd;
}
input[type=range]::-moz-range-track {
width: 100%;
height: 10px;
cursor: pointer;
animate: 0.2s;
box-shadow: 0px 0px 0px #ccc, 0px 0px 0px #ccc;
background: #ddd;
border-radius: 25px;
border: 1px solid #ccc;
}
input[type=range]::-moz-range-thumb {
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
border: 0px solid #2e6da4;
height: 20px;
width: 20px;
border-radius: 7px;
background: #337ab7;
cursor: pointer;
}
input[type=range]::-ms-track {
width: 100%;
height: 10px;
cursor: pointer;
animate: 0.2s;
background: transparent;
border-color: transparent;
border-width: 39px 0;
color: transparent;
float: right;
}
input[type=range]::-ms-fill-lower {
background: #ddd;
border: 0px solid #000101;
border-radius: 50px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-fill-upper {
background: #ddd;
border: 0px solid #000101;
border-radius: 50px;
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
}
input[type=range]::-ms-thumb {
box-shadow: 0px 0px 0px #000000, 0px 0px 0px #0d0d0d;
border: 0px solid #000000;
height: 20px;
width: 20px;
border-radius: 7px;
background: #337ab7;
cursor: pointer;
}
input[type=range]:focus::-ms-fill-lower {
background: #ddd;
}
input[type=range]:focus::-ms-fill-upper {
background: #ddd;
}
button {
background-color: rgb(53, 135, 212);
padding: 3px 9px;
font-size: 14px;
font-weight: 400;
line-height: 1.5;
float: left;
vertical-align: middle;
cursor: pointer;
display: inline-block;
color: #fff;
background: #337ab7;
border: 1px solid #2e6da4;
border-radius: 4px;
}
.controls {
width: 700px;
display: block;
float: left;
padding: 0;
margin: 0;
height: 25px;
}
.controls div {
display: inline-block;
float: right;
margin-left: 10px;
width: 635px;
padding: 0;
height: 25px;
}
.tooltip {
background-color: #f7f7f7;
padding: 3px 12px;
font-family: sans-serif;
border: 1px solid #bbbbbb;
box-shadow: 1px 1px 4px #bbbbbb;
}
.tooltip_title {
font-weight: bold;
font-size: 14px;
margin: 5px 0;
max-width: 300px;
word-wrap: normal;
padding: 5px 0;
margin: -3px -12px 5px -12px;
color: #fff;
}
pre {
font-family: Gotham, "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 12px;
}
.tooltip_body {
font-weight: normal;
margin: 5px 0;
text-align: left;
}
</style>
<h1>2000-2007 CSU Comparisons: Selectable Measures Time-Series Charts</h1>
<p id="chart"></p>
<div class="controls">
<button name="play" id="play">Play</button>
<div><input autocomplete="off" id="slider" type="range" min="2000" max="2007" value="2000" step="1" /></div>
</div>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="https://raw.github.com/fryn/html5slider/gh-pages/html5slider.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script>
$(document).ready(function() {
// Various accessors that specify the four dimensions of data to visualize.
function x(d) { return d.gradrate; }
function y(d) { return d.gap; }
function radius(d) { return d.total; }
function color(d) { return d.campus; }
function key(d) { return d.campus; }
// Chart dimensions.
var margin = {top: 19.5, right: 200, bottom: 19.5, left: 39.5},
width = 860 - margin.right,
height = 400 - margin.top - margin.bottom;
// Various scales. These domains make assumptions of data, naturally.
var xScale = d3.scale.linear().domain([10, 75]).range([0, width]),
yScale = d3.scale.linear().domain([-10, 25]).range([height, 0]),
radiusScale = d3.scale.sqrt().domain([0, 4000]).range([0, 40]),
colorScale = d3.scale.category10();
var formatPercent = d3.format(".0%");
var excluded_groups = [];
// The x & y axes.
var xAxis = d3.svg.axis().orient("bottom").scale(xScale).ticks(12).tickFormat(function(d) { return parseInt(d, 10) + "%"; }).tickSize(-height),
yAxis = d3.svg.axis().scale(yScale).orient("left").tickFormat(function(d) { return parseInt(d, 10) + "%"; }).tickSize(-width);
// Create the SVG container and set the origin.
var svg = d3.select("#chart").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 + ")");
//Tooltip
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden");
// Add the x-axis.
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height +")")
.call(xAxis);
// Add the y-axis.
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
// Add an x-axis label.
svg.append("text")
.attr("class", "x label")
.attr("text-anchor", "end")
.attr("x", width)
.attr("y", height - 6)
.text("Graduation Rate");
// Add a y-axis label.
svg.append("text")
.attr("class", "y label")
.attr("text-anchor", "end")
.attr("y", 6)
.attr("dy", ".75em")
.attr("transform", "rotate(-90)")
.text("Achievement Gap");
// Add the year label; the value is set on transition.
var label = svg.append("text")
.attr("class", "year label")
.attr("text-anchor", "end")
.attr("y", height - 35)
.attr("x", width)
.text(2000);
// Load the data.
d3.json("campus.json", function(error, data) {
if (error) return console.warn(error);
console.log(data);
// A bisector since many nation's data is sparsely-defined.
var bisect = d3.bisector(function(d) { return d[0]; });
// Add a dot per nation. Initialize the data at 1800, and set the colors.
var dot = svg.append("g")
.attr("class", "dots")
.selectAll(".dot")
.data(interpolateData(2000))
.enter().append("circle")
.attr("class", "dot")
//.attr("id", 'tag'+d.campus.replace(/\s+/g, '')) // assign ID
.attr("id", function(d) { return "tag" + d.campus.replace(/\s+/g, '') })
.style("fill", function(d) { return colorScale(color(d)); })
.style("stroke", function(d) { return colorScale(color(d)); })
.call(position)
.sort(order)
.on("mouseover", function(d) {
tooltip.html("");
tooltip.append("h3").attr("class", "tooltip_title")
.style("background-color", colorScale(color(d)))
tooltip.append("pre").attr("class", "tooltip_body");
tooltip.select(".tooltip_title")
.text(d.campus);
tooltip.select(".tooltip_body")
.text(
//"Year: " + year + "\n" +
"Achievement Gap: " + "\u00A0\u00A0" + Math.round(d.gap) + "%\n" +
"Graduation Rate: " + "\u00A0\u00A0" + Math.round(d.gradrate) + "%\n" +
"Total FTF Freshmen: " + "\u00A0\u00A0" + Math.round(d.total) + "\n" +
"Percent Pell: " + "\u00A0\u00A0" + Math.round(d.pell) + "%\n"
);
return tooltip.style("visibility", "visible");
})
.on("mousemove", function() {
return tooltip.style("top", (d3.event.pageY-52) + "px").style("left", (d3.event.pageX+25) + "px");
})
.on("mouseout", function() {
return tooltip.style("visibility", "hidden");
});
// Add a title.
dot.append("title")
.text(function(d) { return d.campus; });
$("button").on("click", function() {
update();
});
$("#slider").on("change", function(){
svg.transition().duration(0);
displayYear($("#slider").val());
});
var update = function() {
// Add a dot per nation. Initialize the data at 1800, and set the colors.
d3.selectAll(".dot")
.data(interpolateData(2000))
.enter().append("circle")
.attr("class", "dot")
.style("fill", function(d) { return colorScale(color(d)); })
.call(position)
.sort(order);
// Add a title.
dot.append("title")
.text(function(d) { return d.campus; });
// Start a transition that interpolates the data based on year.
svg.transition()
.duration(6000)
.ease("linear")
.tween("year", tweenYear)
};//update function
// Positions the dots based on data.
function position(dot) {
dot .attr("cx", function(d) { return xScale(x(d)); })
.attr("cy", function(d) { return yScale(y(d)); })
.attr("r", function(d) { return radiusScale(radius(d)); });
}
// Defines a sort order so that the smallest dots are drawn on top.
function order(a, b) {
return radius(b) - radius(a);
}
// Tweens the entire chart by first tweening the year, and then the data.
// For the interpolated data, the dots and label are redrawn.
function tweenYear() {
var year = d3.interpolateNumber(2000, 2007);
return function(t) { displayYear(year(t)); };
}
// Updates the display to show the specified year.
function displayYear(year) {
dot.data(interpolateData(year), key).call(position).sort(order);
label.text(Math.round(year));
$("#slider").val(Math.round(year));
$(".tooltip_title").text(Math.round(year));
}
// Interpolates the dataset for the given (fractional) year.
function interpolateData(year) {
return data.map(function(d) {
return {
campus: d.campus,
pell: interpolateValues(d.pell, year),
gradrate: interpolateValues(d.gradrate, year),
gap: interpolateValues(d.gap, year),
total: interpolateValues(d.total, year),
};
});
}
// Finds (and possibly interpolates) the value for the specified year.
function interpolateValues(values, year) {
var i = bisect.left(values, year, 0, values.length - 1),
a = values[i];
if (i > 0) {
var b = values[i - 1],
t = (year - a[0]) / (b[0] - a[0]);
return a[1] * (1 - t) + b[1] * t;
}
return a[1];
}
var legend = svg.selectAll(".legend")
.data(data)
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(6," + i * 14 + ")"; });
legend.append("rect")
.attr("x", width)
.attr("width", 12)
.attr("height", 12)
.style("fill", function(d) { return colorScale(color(d)); })
//.style("opacity", .5);
legend.append("text")
.attr("x", width + 16)
.attr("y", 6)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d) { return d.campus; });
legend.on("mouseover", function(d) {
d3.selectAll(".legend")
.style("opacity", 0.1);
d3.select(this)
.style("opacity", 1);
d3.selectAll(".dot")
.style("opacity", 0.1)
d3.selectAll("#tag"+d.campus.replace(/\s+/g, ''))
.style("opacity", 1);
})
.on("mouseout", function(type) {
d3.selectAll(".legend")
.style("opacity", .7);
d3.selectAll(".dot")
.style("opacity", .7);
});
/*legend.on("click", function(d){
// Determine if current line is visable
var active = d.active ? false : true,
newClass = active ? "dot active" : "dot inactive";
// Hide or show the elements based on the ID
d3.selectAll("#tag"+d.campus.replace(/\s+/g, ''))
.attr("class", newClass)
d3.select(this)
//.style("fill", function() {
//if (active) {return "red"}
//})
.style("opacity", function() {
if (active) {return "1"}
})
// Update whether or not the elements are active
console.log(active)
d.active = active
console.log(active)
})*/
});//data function
});//ready
</script>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment