The number of people in New York faceted by self-reported ancestry. Click the "Open" button to the right to see it fullscreen.
Data from the U.S. Census Bureau
The number of people in New York faceted by self-reported ancestry. Click the "Open" button to the right to see it fullscreen.
Data from the U.S. Census Bureau
| <html> | |
| <head> | |
| <link href='https://fonts.googleapis.com/css?family=Raleway:300' rel='stylesheet' type='text/css'> | |
| <style> | |
| html { | |
| font-family: 'Raleway', sans-serif; | |
| } | |
| .map { | |
| display: inline-block; | |
| position: relative; | |
| padding-top: 50px; | |
| } | |
| .map h3 { | |
| text-align: center; | |
| position: absolute; | |
| top: 10px; | |
| left: 10px; | |
| width: 200px; | |
| margin-top: 0px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
| <script> | |
| var width = 300, | |
| height = width; | |
| var fontSizeScale = d3.scale.pow().exponent(0.15) | |
| .domain([0, 1000000]) | |
| .range([0, 50]); | |
| var areaScale = d3.scale.linear() | |
| .domain([0, 1000]) | |
| .range([0, width]); | |
| var projection = d3.geo.mercator() | |
| .center([-73.98, 40.70]) | |
| .scale(30000) | |
| .translate([width/2, height/2]); | |
| var path = d3.geo.path() | |
| .projection(projection); | |
| var container = d3.select("body").append("div") | |
| .attr("class", "container"); | |
| d3.json("nyc.json", function(error, nyc) { | |
| if (error) throw error; | |
| console.log(nyc); | |
| var ancestries = nyc.tracts.properties.ancestries; | |
| ancestries.sort(function(a, b) { | |
| return d3.ascending(a.ancestry_name, b.ancestry_name); | |
| }); | |
| var maps = container.selectAll(".map") | |
| .data(ancestries) | |
| .enter().append("div") | |
| .attr("class", "map"); | |
| maps.append("h3") | |
| .style("font-size", function(d) { | |
| return fontSizeScale(d.people / d.ancestry_name.length); | |
| }) | |
| .text(function(d) { return d.ancestry_name; }); | |
| //// Draw maps | |
| // Do it this way so it starts rendering maps sequentially | |
| // instead of holding off and rendering only after all maps | |
| // are ready. There's got to be a better way... | |
| var canvases = maps.append("canvas") | |
| .attr("width", width) | |
| .attr("height", height)[0]; | |
| var timer = d3.timer(function(t) { | |
| var canvas = canvases.shift(); | |
| if (canvas !== undefined) { | |
| var context = canvas.getContext("2d"), | |
| ancestry_id = canvas.__data__.ancestry_id; | |
| path.context(context); | |
| draw(context, ancestry_id); | |
| } | |
| else { return true; } | |
| }); | |
| function draw(context, ancestry_id) { | |
| // Draw the boroughs | |
| context.lineWidth = 0.2; | |
| context.beginPath(); | |
| path(nyc.boroughs); | |
| context.stroke(); | |
| // Draw the bubbles | |
| context.save(); | |
| context.globalAlpha = 0.7; | |
| context.lineWidth = 0.1; | |
| nyc.tracts.features.forEach(function(d) { | |
| var p = projection(d.geometry.coordinates), | |
| people = d.properties.ancestry[ancestry_id] || 0, | |
| area = areaScale(people), | |
| radius = Math.sqrt(area / Math.PI); | |
| context.beginPath(); | |
| context.arc(p[0], p[1], radius, 0, 2*Math.PI); | |
| context.stroke(); | |
| }); | |
| context.restore(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |