// Various formatters. var formatNumber = d3.format(",d"), formatChange = d3.format("+,d"), formatDate = d3.time.format("%B %d, %Y"), formatTime = d3.time.format("%I:%M %p"); // data across years var extant = []; var width = 960, height = 500; var rateById = d3.map(), popById = d3.map(), nameById = d3.map(); var quantize = d3.scale.quantize() .domain([-.02, .05]) .range(d3.range(9).map(function(i) { return "q" + i + "-9"; })); var path = d3.geo.path(); var svg = d3.select("#map").append("svg") .attr("width", width) .attr("height", height); tip = d3.tip() .attr('class', 'd3-tip') .offset([-10, 0]) .direction('n') .html(function(d) { return nameById.get(d.id) + "
Income change: " + (rateById.get(d.id)*100).toFixed(2) + "%" + "
Population change: " + (popById.get(d.id)*100).toFixed(2) + "%" }); svg.call(tip); var legend = d3.select("#map-legend"). append("svg:svg"). attr("width", 160). attr("height", 10) for (var i = 0; i <= 7; i++) { legend.append("svg:rect"). attr("x", i*20). attr("height", 10). attr("width", 20). attr("class", "q" + i + "-9 ");//color }; var nation = crossfilter(), all = nation.groupAll(), per_cap = nation.dimension(function(d) { return d.Per_capita_personal_income; }), per_caps = per_cap.group(), population = nation.dimension(function(d) { return d.Population; }), populations = population.group(); queue() .defer(d3.json, "counties.json") .defer(d3.tsv, "county_growth.tsv", function(d) { for(var propertyName in d) { if (propertyName == "Area") { continue; }; d[propertyName] = +d[propertyName]; } nation.add([d]); extant.push(d.id); rateById.set(d.id, d.Per_capita_personal_income); popById.set(d.id, d.Population); nameById.set(d.id, d.Area); }) .await(ready); function ready(error, us) { svg.append("g") .attr("class", "counties") .selectAll("path") .data(topojson.feature(us, us.objects.counties).features) .enter().append("path") .attr("class", function(d) { return quantize(rateById.get(d.id)); }) .attr("id", function(d) { return d.id; }) .attr("d", path) .on('mouseover',tip.show) .on('mouseout', tip.hide); var charts = [ barChart(true) .dimension(population) .group(populations) .x(d3.scale.linear() .domain([-.34, .47]) .range([0, 900])), barChart(true) .dimension(per_cap) .group(per_caps) .x(d3.scale.linear() .domain([-.34, .47]) .range([0, 900])) ]; var chart = d3.selectAll(".chart") .data(charts) .each(function(chart) { chart.on("brush", renderAll).on("brushend", renderAll); }); renderAll(); // barChart function barChart(percent) { if (!barChart.id) barChart.id = 0; percent = typeof percent !== 'undefined' ? percent : false; var formatAsPercentage = d3.format(".0%"); var axis = d3.svg.axis().orient("bottom"); if (percent == true) { axis.tickFormat(formatAsPercentage); } var margin = {top: 10, right: 10, bottom: 20, left: 10}, x, y = d3.scale.linear().range([50, 0]), id = barChart.id++, brush = d3.svg.brush(), brushDirty, dimension, group, round; function chart(div) { var width = x.range()[1], height = y.range()[0]; try { y.domain([0, group.top(1)[0].value]); } catch(err) { window.reset } div.each(function() { var div = d3.select(this), g = div.select("g"); // Create the skeletal chart. if (g.empty()) { div.select(".title").append("a") .attr("href", "javascript:reset(" + id + ")") .attr("class", "reset") .text("reset") .style("display", "none"); g = 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 + ")"); g.append("clipPath") .attr("id", "clip-" + id) .append("rect") .attr("width", width) .attr("height", height); g.selectAll(".bar") .data(["background", "foreground"]) .enter().append("path") .attr("class", function(d) { return d + " bar"; }) .datum(group.all()); g.selectAll(".foreground.bar") .attr("clip-path", "url(#clip-" + id + ")"); g.append("g") .attr("class", "axis") .attr("transform", "translate(0," + height + ")") .call(axis); // Initialize the brush component with pretty resize handles. var gBrush = g.append("g").attr("class", "brush").call(brush); gBrush.selectAll("rect").attr("height", height); gBrush.selectAll(".resize").append("path").attr("d", resizePath); } // Only redraw the brush if set externally. if (brushDirty) { brushDirty = false; g.selectAll(".brush").call(brush); div.select(".title a").style("display", brush.empty() ? "none" : null); if (brush.empty()) { g.selectAll("#clip-" + id + " rect") .attr("x", 0) .attr("width", width); } else { var extent = brush.extent(); g.selectAll("#clip-" + id + " rect") .attr("x", x(extent[0])) .attr("width", x(extent[1]) - x(extent[0])); } } g.selectAll(".bar").attr("d", barPath); }); function barPath(groups) { var path = [], i = -1, n = groups.length, d; while (++i < n) { d = groups[i]; path.push("M", x(d.key), ",", height, "V", y(d.value), "h9V", height); } return path.join(""); } function resizePath(d) { var e = +(d == "e"), x = e ? 1 : -1, y = height / 3; return "M" + (.5 * x) + "," + y + "A6,6 0 0 " + e + " " + (6.5 * x) + "," + (y + 6) + "V" + (2 * y - 6) + "A6,6 0 0 " + e + " " + (.5 * x) + "," + (2 * y) + "Z" + "M" + (2.5 * x) + "," + (y + 8) + "V" + (2 * y - 8) + "M" + (4.5 * x) + "," + (y + 8) + "V" + (2 * y - 8); } } brush.on("brushstart.chart", function() { var div = d3.select(this.parentNode.parentNode.parentNode); div.select(".title a").style("display", null); }); brush.on("brush.chart", function() { var g = d3.select(this.parentNode), extent = brush.extent(); if (round) g.select(".brush") .call(brush.extent(extent = extent.map(round))) .selectAll(".resize") .style("display", null); g.select("#clip-" + id + " rect") .attr("x", x(extent[0])) .attr("width", x(extent[1]) - x(extent[0])); var selected = []; dimension.filterRange(extent).top(Infinity).forEach(function(d) { selected.push(d.id) }); svg.attr("class", "counties") .selectAll("path") .attr("class", function(d) { if (selected.indexOf(d.id) >= 0) {return "q8-9"} else if (extant.indexOf(d.id) >= 0) {return "q5-9"} else {return null;}}); }); brush.on("brushend.chart", function() { if (brush.empty()) { var div = d3.select(this.parentNode.parentNode.parentNode); div.select(".title a").style("display", "none"); div.select("#clip-" + id + " rect").attr("x", null).attr("width", "100%"); dimension.filterAll(); } }); chart.margin = function(_) { if (!arguments.length) return margin; margin = _; return chart; }; chart.x = function(_) { if (!arguments.length) return x; x = _; axis.scale(x); brush.x(x); return chart; }; chart.y = function(_) { if (!arguments.length) return y; y = _; return chart; }; chart.dimension = function(_) { if (!arguments.length) return dimension; dimension = _; return chart; }; chart.filter = function(_) { if (_) { brush.extent(_); dimension.filterRange(_); } else { brush.clear(); dimension.filterAll(); } brushDirty = true; return chart; }; chart.group = function(_) { if (!arguments.length) return group; group = _; return chart; }; chart.round = function(_) { if (!arguments.length) return round; round = _; return chart; }; return d3.rebind(chart, brush, "on"); } // Renders the specified chart or list. function render(method) { d3.select(this).call(method); } // Whenever the brush moves, re-rendering everything. function renderAll() { chart.each(render); } window.filter = function(filters) { filters.forEach(function(d, i) { charts[i].filter(d); }); renderAll(); }; window.reset = function(i) { charts.forEach(function (c) { c.filter(null); }) renderAll(); svg.attr("class", "counties") .selectAll("path") .attr("class", function(d) { return quantize(rateById.get(d.id)); }); }; }