Upload
vivian-shangxuan-zhang
View
819
Download
0
Embed Size (px)
DESCRIPTION
find us at http://www.meetup.com/NYC-Open-Data/events/137298432/ Hack Session 2: New Yorker Magazine Vis---Inequality and New York’s Subway Magazine link: http://www.newyorker.com/sandbox/business/subway.html
Citation preview
Data Source
Projection,data
Map
New York’s mapSubway lineStation(position)
Scale,Axis,line
ChartAxisBackgroundLabelPathStation
AttributeClass,id,etc..
drawChart([json]);
topojson tabletop
subway lineNew York city
subway_inequality_live(excel from google doc)
<script src="topojson.v0.min.js"></script>var sourceData;window.onload = function() { init() };
var url = 'https://docs.google.com/spreadsheet/pub?key=0ApL2ZVhpOmONdFdTUWhxV252elNORVNqT0g5Y0NzV1E&output=html';
function init() { Tabletop.init( { key: url, callback: show, simpleSheet: true } ); }function show(data) { sourceData = data; drawChart(); }
<script type="text/javascript" src="tabletop.js"></script>
New York city map
Subway line
D3.geo.mercator()
d3.geo.path().projection
data(map data).enter().append(“path”).attr(“d”,path)
var projection = d3.geo.mercator() .center([-73.955, 40.678) .translate([w/2, h/2]) .scale([34000]);
var path = d3.geo.path() .projection(projection);
var g = svg.append("g") .attr("class", "borough_lines");
create map
var w = 400; var h = 400;
var svg = d3.select("#map") .append("svg") .attr("width", w) .attr("height", h);
create map
g.selectAll("path.borough_map") .data(topojson.object(nyc_boroughs[0], nyc_boroughs[0].objects.new_york_city_boroughs).geometries) .enter() .append("path") .attr("d", path) .attr("class", "borough_map");
create map
create map
var g1 = svg.append("g") .attr("class", "map_lines");
g1.selectAll("path.map_line") .data(topojson.object(subway_lines[0], subway_lines[0].objects.subways).geometries) .enter() .append("path") .attr("d", path) .attr("class", function(d){ return "map_line l_" + d.properties.route_id }) .style("fill", "white") .style("fill-opacity", 0) .style("opacity", .5) .style("stroke-width", 3) .style("stroke-linecap", "round");
svg.selectAll("circle.map_circle") .data(sourceData) .enter() .append("circle") .attr("cx", function(d){//transform position return projection([d.long, d.lat])[0]; }) .attr("cy", function(d){ return projection([d.long, d.lat])[1]; }) .attr("r", 4) .attr("id", function(d){ return "t_" + d.county + "_" + d.tract }) .attr("opacity", 0);
create map
point marker : t_61_24302 hidden
LabelFormat,tick
lineD3.svg.line().x().y().interpolate()
container
DataAxis
d3.scale.linear()d3.svg.axis().scale();
Bla.call(↑)
30px
900px
500px
118px20px
var containerSize = { width : 900, height : 400 },
margins = {top : 20,right : 20,bottom : 30,left : 118},
chartSize = { width : containerSize.width - margins.left - margins.right - 20, height : containerSize.height - margins.top - margins.bottom };
create chart
var chart = d3.select("#graphic") .append("svg") .attr("width", containerSize.width) .attr("height", containerSize.height) .append("g") .attr("transform", "translate(" + margins.left + "," + margins.top + ")") .attr("id","chart");
var test_scale = d3.scale.linear() .range([0,100) .domain([0, 10]);
test_scale(5)? Get 50px
Test_scale(0)? Get 0 px
What is scale?
X: test_scale
100px
Data: [{x:5},{y:0}]
X position,50px
Y position,0px
var stop_scale = d3.scale.linear() .range([0,chartSize.width]) .domain([1, 49]);
var incomeScale = d3.scale.linear() //data range .range([chartSize.height, 0]) .domain([0,230000]); //income axis, max230000
Make the scale
X: stop_scaleY: incomeScale
var stop_axis = d3.svg.axis() .scale(stop_scale);
var incomeAxis = d3.svg.axis() .scale(incomeScale) .orient("left") .tickValues([0, 50000, 100000, 150000, 200000])//tick .tickSize(-chartSize.width, 0) .tickPadding(20) .tickFormat(function(d) { return "$" + formatNum(d); });
//format number
Make the axis
convert 10000 to 10,000 function formatNum(d){ return d.toString().replace(/(?=(?!\b)(?:\d{3})+(?!\d))/g, ',') }
var line2011Path = d3.svg.line() .x(function(d){return stop_scale(d.position)}) .y(function(d){return incomeScale(d.income2011)}) .interpolate("cardinal");
create line
g.selectAll("circle") .data(sourceData) .enter() .append("circle");
window ['lineBox'] = g //dispose
chart.append("g") .attr("class", "y axis") .call(incomeAxis);
Make the chart d3.select("#chart") .append("g") .attr("id", "areaBox");
d3.select(".y.axis") .append("text") .attr("text-anchor","middle") .text("median household income") .attr("transform", "rotate (270, 0, 0)") .attr("x", -180) .attr("y", -110);
var g = d3.select("#chart") .append("g") .attr("id","line_path_2011";
g.append("path");
map
Hide all lineShowLine (id)
Hide all pointsMatching pathTransition path (id)Show related points (brushed data)
chart
Trigger by Button
Whole data
brushed data
By “id”
<div class="line l_1">1</div> <div class="line l_2">2</div> <div class="line l_3">3</div> <div class="line l_4">4</div> <div class="line l_5">5</div> <div class="line l_6">6</div> <div class="line l_7">7</div>...... <div class="line l_J">J</div> <div class="line l_Z">Z</div> <div class="line l_G">G</div> <div class="line l_L">L</div> <div class="line l_SIR">SIR</div>
Class: line l_1
Create button
use css to color the line
.l_123, .l_1, .l_2, .l_3 { background-color: #FF3535; stroke: #FF3535;} .l_456, .l_4, .l_5, .l_6 { background-color: #019733; stroke: #019733;} .l_7 { background-color: #CC02C8; stroke: #CC02C8;} .l_ace, .l_A, .l_C, .l_E { background-color: #0F6797; stroke: #0F6797;} .l_bdfm, .l_B, .l_D, .l_F, .l_M { background-color: #FF9800; stroke: #FF9800;} .l_nqr, .l_N, .l_Q, .l_R { background-color: #ffe400; stroke: #ffe400;} .l_SIR { background-color: #164480; stroke: #164480;} .l_jz, .l_J, .l_Z { background-color: #986701; stroke: #986701;} .l_L, .l_l { background-color: #999999; stroke: #999999;} .l_G, .l_g { background-color: #9BCF00; stroke: #9BCF00;}
Make the transition
d3.selectAll(".line") .on(“click”, brushData)
function brushData(){ id = d3.select(this).text(); filteredData = sourceData.filter(function(d){return d.line === id}); drawLine(filteredData, id); }
function drawLine(filteredData, id){
…Draw chart line(l_+id)…Draw subway (l_+id)…Show circles(filteredData)
}
Show circles(filteredData)
d3.selectAll("circle") .transition() .duration(500) .attr("r", 0);//minimize all circlewindow['lineBox'].selectAll("circle") .data(filteredData) .transition() .duration(1000) .attr("r", 4) .attr("class", function(d) {return "t_" + d.county + "_" + d.tract }) .attr("cx", function(d) {return stop_scale(d.position)}) .attr("cy", function(d) {return incomeScale(d.income2011)});
function drawLine(filteredData, id){Draw chart line(l_+id)Draw subway (l_+id)Show circles(filteredData)}
Draw chart line(l_+id)
d3.select("#line_path_2011 path") .attr("class", "graph_line l_" + id .transition() .duration(1000) .attr("d", line2011Path(filteredData)
function drawLine(filteredData, id){Draw chart line(l_+id)Draw subway (l_+id)Show circles(filteredData)}
var line2011Path = d3.svg.line() .x(function(d){return stop_scale(d.position)}) .y(function(d){return incomeScale(d.income2011)}) .interpolate("cardinal");
Draw subway (l_+id)
//hideall d3.selectAll(".map_line") .transition() .duration(500) .style("opacity", 0);
//show d3.selectAll(".map_line.l_" + id) .transition() .duration(500) .style("opacity", 1);
function drawLine(filteredData, id){Draw chart line(l_+id)Draw subway (l_+id)Show circles(filteredData)}
d3.selectAll(".line") .classed("selected", false);
d3.select(".line.l_" + id) .classed("selected", true);
Create info box
<div id="tooltip" class="">
<div class="line l_F ">F</div> <div id="stop-name"> <span id="name">East Broadway</span> </div> <div class="label-wrap"> <div class="label-number" id="income2011">$86,806</div> <div class="label">2011 median household income in census tract <span id="census">001401</span></div> </div>
</div>
Define point activity
//hover overs/interactions d3.selectAll("circle") .on("mouseover", function(d) {
//Show tooltip(mouse position)//Bigger the point on chart//Insert content//Show the point on map
}) .on("mouseout", function() { //hide tooltip
//Smaller the point });
d3.select(this) .transition() .attr("r", 8); d3.select("#tooltip") .style("left", (d3.event.pageX) + 20 + "px") .style("top", (d3.event.pageY) - 30 + "px").transition() .style("opacity", 1); d3.select('#stop-name #name') .text(d.stopname) d3.select('#tooltip .line') .text(id) .attr("class", "line l_" + id, true)
d3.select('#income2011') .text("$" + formatNum(d.income2011)); d3.select('#census') .text(d.tractlookup);
d3.select("circle#" + this.className.animVal) .transition() .duration(500) .attr("opacity", 1) .attr("r", 5);
Bigger the point on chart
Show tooltip
Show point on map
Fill the content
//Hide the tooltip d3.select("#tooltip") .transition() .style("opacity", 0);
d3.select(this) .transition() .attr("r", 4);
d3.selectAll("#map circle") .transition() .duration(500) .attr("opacity", 0);
Hide tooltip
Hide point on map
Smaller point on chart
Cut the county
Span: how many points
Start:where we can draw the next county
County:id
Whole data
Filtered data
Memo:[]
Reduce data
Match the line “id”
County change?
yesno
Push new county data(start,span,county)
Span++
Filter data
Boroughs = filteredData.reduce(
function (memo, stop, i) {var len = memo.length;if (len == 0 || (memo[len - 1].county != stop.county)) {
memo.push({county : stop.county,start : i + 1,span : 1 });
} else {memo[len - 1].span++;
}return memo;
},[])
[{"county":"47","start":1,"span":19},{"county":"61","start":20,"span":15}]
Draw county
var gCounties = d3.select("#areaBox") .selectAll('g.borough')
.data(boroughs).enter() .append('g') .attr('class', 'borough') .attr('transform', function (d) return 'translate(' + stop_scale(d.start) +
')'; });
Add label
gCounties.append('text') .attr("y", 15) .text(function (d) { if (d.county == "5") { return "BRX" } else if (d.county == "61") { return "MAN" } else if (d.county == "81") { return "QNS" } else if (d.county == "47") { return "BRK" }; });
gCounties.append('rect') .attr('x', -5) .attr('width', function (d) { return stop_scale(d.span + .8) }) .attr('height', chartSize.height);