Data Source Projection,dat a Map New York’s map Subway line Station(positio n) Scale,Axis,line Chart Axis Background Label Path Station Attribute Class,id,etc..
May 10, 2015
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);