D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
rambler
Full window
Github gist
Homelessness over time in the USA
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Homelessness in the USA</title> <script type="text/javascript" src="https://d3js.org/d3.v3.js"></script> <style type="text/css"> body { background-color: white; font-family: Helvetica, Arial, sans-serif; } h1 { font-size: 24px; margin: 0; } p { font-size: 14px; margin: 10px 0 0 0; } svg { background-color: white; } circle:hover { fill: orange; } .axis path, .axis line { fill: none; stroke: black; shape-rendering: crispEdges; } .axis text { font-family: sans-serif; font-size: 11px; } div.tooltip { position: absolute; text-align: center; width: 120px; height:71px; padding: 2px; font: 12px sans-serif; background: lightsteelblue; border: 0px; border-radius: 8px; /* pointer-events: none; This line needs to be removed */ } </style> </head> <body> <h1>Homelessness in the USA</h1> <p>This document shows homelessness over time in the USA. Each state appears as a different band in the stacked area.</p> <p>Hovering over each state will show sparklines with the unsheltered (red) and sheltered (blue) components of the total for that state over the same time period.</p> <script type="text/javascript"> //Dimensions and padding var margin = {top: 20, right: 10, bottom: 50, left: 100} var w = 800 - margin.left - margin.right; var h = 400 - margin.top - margin.bottom; //Set up scales var x = d3.scale.ordinal() .rangeRoundBands([0, w], 0.1); var y = d3.scale.linear() .range([h, 0]); //Configure axis generators var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left"); var stack = d3.layout.stack() .offset("zero") .values(function (d) { return d.values; }) .x(function (d) { return x(d.year); }) .y(function (d) { return +d.value; }); var area = d3.svg.area() .interpolate("cardinal") .x(function (d) { return x(d.year); }) .y0(function (d) { return y(d.y0); }) .y1(function (d) { return y(d.y0 + d.y); }); var color = d3.scale.category20b(); var svg = d3.select("body") .append("svg") .attr("width", w + margin.left + margin.right) .attr("height", h + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); // Define 'div' for tooltips var div = d3.select("body") .append("div") // declare the tooltip div .attr("class", "tooltip") // apply the 'tooltip' class .style("opacity", 0); // set the opacity to nil d3.json("State_merged.json", function (stateData) { var mergedData = []; var maxHomeless = 0; var years = {}, states = {}, varNames = {}; var endStateCount = {}; Object.keys(stateData).forEach(function (state) { //console.log(state); states[state] = true; Object.keys(stateData[state]).forEach(function (year) { years[year] = true; stateData[state][year].state = state; stateData[state][year].year = year; stateData[state][year].value = +stateData[state][year].total_homeless; //var total_homeless = stateData[state][year].total_homeless; //console.log(state+','+year+','+stateData[state][year].total_homeless); Object.keys(stateData[state][year]).forEach(function (l) { varNames[l] = true; }) mergedData.push(stateData[state][year]); }); endStateCount[state] = stateData[state]["2014"].value; }); console.log(endStateCount); years = Object.keys(years).sort(); states = Object.keys(states).sort(function (a, b) { console.log(endStateCount[b]); return endStateCount[a] - endStateCount[b]; }); console.log(states); varNames = Object.keys(varNames).sort(); var seriesArr = [], series = {}; states.forEach(function (state) { if (state === "Total") { return; } var values = [] years.forEach(function (year) { values.push(stateData[state][year]); }) series[state] = {state: state, values: values}; seriesArr.push(series[state]); }); //console.log(seriesArr); x.domain(years); y.domain([0, d3.max(mergedData, function (d) { return +d.total_homeless; }) ]); stack(seriesArr); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(-40," + (h) + ")") .call(xAxis); svg.append("g") .attr("class", "y axis") //.attr("transform", "translate(" + (margin.bottom) + ",0)") .call(yAxis); svg.append("text") .attr("class", "x label") .attr("text-anchor", "end") .attr("x", w) .attr("y", h - 6) .text("Year"); svg.append("text") .attr("class", "y label") .attr("text-anchor", "end") .attr("y", -66) .attr("x", 0) .attr("dy", ".75em") .attr("transform", "rotate(-90)") .text("Homeless population"); var selection = svg.selectAll(".series") .data(seriesArr) .enter().append("g") .attr("class", "series") .on("mouseover", function (d) { console.log(d.values); div.transition() .duration(500) .style("opacity", 0); div.transition() .duration(200) .style("opacity", .9); div.html(d.state + ": " + (stateData[d.state]["2007"].total_homeless + " (2007) - " + stateData[d.state]["2014"].total_homeless) + " (2014)") .style("left", (d3.event.pageX) + "px") .style("top", (d3.event.pageY - 28) + "px"); var dataset = []; years.forEach(function(year) { dataset.push(stateData[d.state][year]); }); var w2 = 100; var h2 = 30; var svg2 = div.append("svg") .attr("width", w2-10) .attr("height", h2+10) .append("g"); console.log(years); var x2 = d3.scale.ordinal() .domain(years) .rangeRoundBands([0, w2], 0.04); var ymax = d3.max(dataset, function(d) { if(+d.sheltered_homeless > +d.unsheltered_homeless) { return +d.sheltered_homeless; } return +d.unsheltered_homeless; }); console.log("Ymax: "+ymax); var y2 = d3.scale.linear() .domain([0, ymax]) .range([h2, 0]); var line2 = d3.svg.line() .interpolate("basis") .x(function(d) { console.log(d.year); return x2(d.year); }) .y(function(d) { console.log(d.unsheltered_homeless); return 5+y2(d.unsheltered_homeless)}); var line3 = d3.svg.line() .interpolate("basis") .x(function(d) { return x2(d.year); }) .y(function(d) { return 5+y2(d.sheltered_homeless)}); svg2.append("path") .attr("d", line2(dataset)) .attr("class", "linePath") .attr("fill", "none") .attr("stroke", "#FF0000") .attr("stroke-width", 1); svg2.append("path") .attr("d", line3(dataset)) .attr("class", "linePath") .attr("fill", "none") .attr("stroke", "#0000FF") .attr("stroke-width", 1); console.log("appended.") }); selection.append("path") .attr("class", "stackedArea") .attr("d", function (d) { return area(d.values); }) .style("fill", function (d) { return color(d.state); }) .style("stroke", "grey"); }); </script> </body> </html>
Modified
http://d3js.org/d3.v3.js
to a secure url
https://d3js.org/d3.v3.js