|
<!DOCTYPE html> |
|
<head> |
|
<meta charset="utf-8"> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> |
|
<style> |
|
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0;font: 10px sans-serif; } |
|
svg { width:100%; height: 100% } |
|
.axis line, |
|
.axis path { |
|
fill: none; |
|
stroke: #000; |
|
shape-rendering: crispEdges; |
|
} |
|
|
|
.arrow { |
|
stroke: #000; |
|
stroke-width: 1.5px; |
|
} |
|
|
|
</style> |
|
</head> |
|
|
|
<body> |
|
<script> |
|
var margin = {top: 30, right: 40, bottom: 40, left: 30}, |
|
width = 960 - margin.left - margin.right, |
|
height = 500 - margin.top - margin.bottom; |
|
|
|
var x = d3.scale.linear() |
|
.domain([0, 100]) |
|
.range([0, width-5]) |
|
|
|
var y = d3.scale.ordinal() |
|
.domain(["A+", "A", "A-", "B+", "B", "B-", "C+", "C", "C-", "D+", "D", "D-", "F"]) |
|
.rangeRoundPoints([height, 0]) |
|
|
|
var r = d3.scale.sqrt() |
|
.domain([1, 15]) |
|
.range([4, 20]) |
|
|
|
var xAxis = d3.svg.axis() |
|
.scale(x) |
|
.orient("bottom"); |
|
|
|
var yAxis = d3.svg.axis() |
|
.scale(y) |
|
.orient("right"); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height) |
|
.append("g") |
|
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); |
|
|
|
var plot = svg.append("g") |
|
var axesG = svg.append("g") |
|
var overlayG = svg.append("g").style("font-size", "16px") |
|
|
|
|
|
axesG.append("g") |
|
.attr("class", "x axis") |
|
.attr("transform", "translate(0," + height + ")") |
|
.call(xAxis) |
|
.append("text") |
|
.text("Brady Campaign To End Gun Violence - Percentage Approval") |
|
.attr({dx: width/2 + "px", dy: "30px"}) |
|
.style("text-anchor", "middle") |
|
|
|
|
|
axesG.append("g") |
|
.attr("class", "y axis") |
|
.attr("transform", "translate(" + width + ",0)") |
|
.call(yAxis) |
|
.append("text") |
|
.text("National Rifle Association - Letter Grade") |
|
.attr({dx: -height/2 + "px", dy: "30px", transform: "rotate(-90)"}) |
|
.style("text-anchor", "middle") |
|
|
|
// The circles are actually pie charts, but the data contains no overlap |
|
var pie = d3.layout.pie(); |
|
var arc = d3.svg.arc().innerRadius(function(){return 0}); |
|
|
|
d3.csv("gun_data.csv", function(err, data){ |
|
if (err) return console.error(err); |
|
var map = d3.map(); |
|
data.forEach(function(d){ |
|
var key = [d.brady, d.nra] |
|
var oldVal = map.get(key) || []; |
|
oldVal.push(d) |
|
map.set(key, oldVal) |
|
}) |
|
|
|
plot.selectAll(".data") |
|
.data(map.values()) |
|
.enter() |
|
.append("g") |
|
.attr("transform", function(a){ |
|
var dx = x(+a[0].brady); |
|
var dy = y(a[0].nra); |
|
return "translate("+dx+","+dy+")" |
|
}) |
|
.each(function(a){ |
|
var reps = a.filter(function(d){return d.party == "Republican"}).length; |
|
var dems = a.filter(function(d){return d.party == "Democratic"}).length; |
|
var inds = a.filter(function(d){return d.party == "Independent"}).length; |
|
pieSlices = pie([reps, dems, inds]); |
|
|
|
var sel = d3.select(this); |
|
arc.outerRadius(function(){return r(a.length)}) |
|
sel.selectAll("path") |
|
.data(pieSlices) |
|
.enter() |
|
.append("path") |
|
.attr("d", arc) |
|
.attr("fill", function(d, i){return ["#FF4136", "#0074D9", "#AAAAAA"][i]}) |
|
}) |
|
.on("mouseleave", function(a){ |
|
overlayG.selectAll("*").remove(); |
|
}) |
|
.on("mouseenter", function(a){ |
|
overlayG.append("text") |
|
.text("NRA: "+ a[0].nra + " Brady: " + a[0].brady+"%") |
|
overlayG.selectAll("foo") |
|
.data(a) |
|
.enter() |
|
.append("text") |
|
.text(function(d){ |
|
return d.senator + " " + d.party.charAt(0) + "-" + d.state |
|
}) |
|
.attr("dx", 10) |
|
.attr("dy", function(d, i){ return (i+1) * 20}) |
|
}) |
|
|
|
}) |
|
|
|
</script> |
|
</body> |