var margin = {top: 15, right: 20, bottom: 40, left: 40}, width = 575 - margin.left - margin.right, height = 460 - margin.top - margin.bottom; var parseYear = d3.time.format("%Y").parse, parseDate = d3.time.format("%Y%m").parse, parseMonth = d3.time.format("%m-%Y").parse, numberFormat = d3.format(",.0f"), numberFormatDetailed = d3.format(",.1f"); var x = d3.scale.linear() .range([0, width]); var y = d3.scale.linear() .range([height, 0]); var xAxis = d3.svg.axis() .scale(x) .orient("bottom"); var yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(numberFormatDetailed) .tickSize(-width) .ticks(8); var svg = d3.select("#chart").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 + ")"); var tooltip = d3.select("body").append("div") .attr("class", "tooltip") .style("opacity", 0); var duration = 375; var coordinates; var mouseX; var selectedVariable = "scatter" d3.csv("data.csv", function(error, data) { d3.select("#switchMajor").on("click.chart", function(){ d3.selectAll(".button") .classed("selected",false); d3.select(this) .classed("selected",true); updateChartMajor(); }); d3.select("#switchDetailed").on("click.chart", function(){ d3.selectAll(".button") .classed("selected",false); d3.select(this) .classed("selected",true); updateChartDetailed(); }); data.forEach(function(d) { d.avg_income_1999 = +d.avg_income_1999/1000; d.avg_income_2014 = +d.avg_income_2014; d.income_growth_9914 = +d.income_growth_9914; d.major_avg_income_1999 = +d.major_avg_income_1999/1000; d.major_avg_income_2014 = +d.major_avg_income_2014; d.major_income_growth_9914 = +d.major_income_growth_9914; d.opacity = +d.opacity; }); x.domain([10,70]); y.domain([d3.min(data,function (d) { return 0.85*d.major_income_growth_9914}),4]); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0," + height + ")") .call(xAxis) .append("text") .attr("dy", "2.8em") .attr("dx", width/1.6) .style("text-anchor","end") .attr("class", "xlabel") .text("Average income, 1999, $'000'"); svg.append("g") .attr("class", "y axis") .call(yAxis); svg.append("text") .attr("class", "left label") .text("Average annual income growth, 1999-2014, %") .attr("transform", "rotate(-90)") .style("text-anchor", "middle") .attr("x", -180) .attr("y", -30); svg.selectAll(".scatter") .data(data) .enter() .append("circle") .attr("class", function(d) { return 'code' + d.major_code; }) .classed("scatter", true) .style("opacity", function(d) { return d.opacity;}) .attr("r", function(d) { return 15*(Math.pow((d.major_tot_emp_2014/1000000/3.14),0.5));}) .attr("cx", function(d) { return x(d.major_avg_income_1999); }) .attr("cy", function(d) { return y(d.major_income_growth_9914); }); var line = d3.svg.line() .x(function(d) { return x(d.major_avg_income_1999); }) .y(function(d) { return y(d.major_pred_income_growth); }); var trend = svg.append("path") .datum(data) .attr("class", "trendline") .attr("d", line); var inflation = svg.append("g") .attr("id", "inflation") .append("line") .attr("x1", 0) .attr("y1", y(2.37163)) .attr("x2", width) .attr("y2", y(2.37163)) .style("stroke", "#454545") .style("stroke-width", "2px") .style("stroke-dasharray", "5,5"); d3.select("#inflation") .append("text") .text("Inflation") .attr("x", width-45) .attr("y", y(2.4)) .style("font-family", "Officina, Calibri, Arial") .style("font-size", "13px") .style("fill", "#454545"); var legend = svg.append("g") .attr("class", "legend") .attr("transform", "translate(" + (width - 50) + "," + (height - 20) + ")") .selectAll("g") .data([5e6, 1e7, 2e7]) .enter().append("g"); legend.append("circle") .attr("cy", function(d) { return -15*(Math.pow(((d)/1000000/3.14),0.5));}) .attr("r", function(d) { return 15*(Math.pow(((d)/1000000/3.14),0.5));}); legend.append("text") .attr("y", function(d) { return -30*(Math.pow(((d)/1000000/3.14),0.5));}) .attr("dy", "1.1em") .text(d3.format(".1s")); legend.append("text") .attr("dy", "-85px") .text("Total employment"); d3.selectAll(".scatter") .on("mouseover", function(d) { d3.select(this) .style("fill","#006E9B") .style("opacity",1); coordinates = d3.mouse(this); mouseX = coordinates[0]; tooltip .html( "

" + d.major_occupation + "

" + "

Total employment in 2014: " + numberFormat(d.major_tot_emp_2014) + "

" + "

Avg income 1999: $" + numberFormat(1000*(d.major_avg_income_1999)) + "

" + "

Avg income 2014: $" + numberFormat(d.major_avg_income_2014) + "

" + "

Income growth, 1999-2014: " + numberFormatDetailed(d.major_income_growth_9914) + "% per year

" ) .style("left", (d3.event.pageX - 25) + "px") .style("top", (d3.event.pageY - 140) + "px") .transition() .duration(250) .style("display", "block") .style("opacity", 0.95); if (mouseX > (0.6*width)) { tooltip .style("left", (d3.event.pageX - 200) + "px") } }) .on("mouseout", function(d) { tooltip .transition() .duration(250) .style("opacity", 0) .style("display", "none"); d3.select(this) .style("fill","#00a1ce") .style("opacity", function(d) { return d.opacity;}); d3.selectAll(".scatter") .style("fill","#ddd"); d3.selectAll("." + selectedVariable) .style("fill","#00a1ce"); }); function updateChartMajor() { x.domain([10,70]); y.domain([d3.min(data,function (d) { return 0.85*d.major_income_growth_9914}),4]); xAxis = d3.svg.axis() .scale(x) .orient("bottom"); yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(numberFormatDetailed) .tickSize(-width) .ticks(8); d3.select(".x.axis") .attr("transform", "translate(0," + height + ")") .transition() .duration(duration) .call(xAxis); d3.select(".y.axis") .transition() .duration(duration) .call(yAxis); d3.selectAll(".scatter") .transition() .duration(duration) .ease("linear") .style("opacity", function(d) { return d.opacity;}) .attr("r", function(d) { return 15*(Math.pow((d.major_tot_emp_2014/1000000/3.14),0.5));}) .attr("cx", function(d) { return x(d.major_avg_income_1999); }) .attr("cy", function(d) { return y(d.major_income_growth_9914); }); line = d3.svg.line() .x(function(d) { return x(d.major_avg_income_1999); }) .y(function(d) { return y(d.major_pred_income_growth); }); trend .attr("d", line); d3.selectAll(".scatter") .on("mouseover", function(d) { d3.select(this) .style("fill","#006E9B") .style("opacity",1); coordinates = d3.mouse(this); mouseX = coordinates[0]; tooltip .html( "

" + d.major_occupation + "

" + "

Total employment in 2014: " + numberFormat(d.major_tot_emp_2014) + "

" + "

Avg income 1999: $" + numberFormat(1000*(d.major_avg_income_1999)) + "

" + "

Avg income 2014: $" + numberFormat(d.major_avg_income_2014) + "

" + "

Income growth, 1999-2014: " + numberFormatDetailed(d.major_income_growth_9914) + "% per year

" ) .style("left", (d3.event.pageX - 25) + "px") .style("top", (d3.event.pageY - 140) + "px") .transition() .duration(250) .style("display", "block") .style("opacity", 0.95); if (mouseX > (0.6*width)) { tooltip .style("left", (d3.event.pageX - 200) + "px") } }) .on("mouseout", function(d) { tooltip .transition() .duration(250) .style("opacity", 0) .style("display", "none"); d3.select(this) .style("fill","#00a1ce") .style("opacity", function(d) { return d.opacity;}); d3.selectAll(".scatter") .style("fill","#ddd"); d3.selectAll("." + selectedVariable) .style("fill","#00a1ce"); }); d3.select(".legend") .remove(); legend = svg.append("g") .attr("class", "legend") .attr("transform", "translate(" + (width - 50) + "," + (height - 20) + ")") .selectAll("g") .data([5e6, 1e7, 2e7]) .enter().append("g"); legend.append("circle") .attr("cy", function(d) { return -15*(Math.pow(((d)/1000000/3.14),0.5));}) .attr("r", function(d) { return 15*(Math.pow(((d)/1000000/3.14),0.5));}); legend.append("text") .attr("y", function(d) { return -30*(Math.pow(((d)/1000000/3.14),0.5));}) .attr("dy", "1.1em") .text(d3.format(".1s")); legend.append("text") .attr("dy", "-85px") .text("Total employment"); } function updateChartDetailed() { x.domain([10,110]); y.domain([d3.min(data,function (d) { return 0.85*d.income_growth_9914}),d3.max(data,function (d) { return 1.12*d.income_growth_9914})]); xAxis = d3.svg.axis() .scale(x) .orient("bottom"); yAxis = d3.svg.axis() .scale(y) .orient("left") .tickFormat(numberFormatDetailed) .tickSize(-width); d3.select(".x.axis") .attr("transform", "translate(0," + height + ")") .transition() .duration(duration) .call(xAxis); d3.select(".y.axis") .transition() .duration(duration) .call(yAxis); d3.selectAll(".scatter") .transition() .duration(duration) .ease("linear") .style("opacity", 0.6) .attr("r", function(d) { return 20*(Math.pow((d.tot_emp_2014/1000000/3.14),0.5));}) .attr("cx", function(d) { return x(d.avg_income_1999); }) .attr("cy", function(d) { return y(d.income_growth_9914); }); line = d3.svg.line() .x(function(d) { return x(d.avg_income_1999); }) .y(function(d) { return y(d.pred_income_growth); }); trend .attr("d", line); d3.selectAll(".scatter") .on("mouseover", function(d) { d3.select(this) .style("fill","#006E9B") .style("opacity",1); coordinates = d3.mouse(this); mouseX = coordinates[0]; d3.select(".tooltip") .html( "

" + d.occupation + "

" + "

Total employment in 2014: " + numberFormat(d.tot_emp_2014) + "

" + "

Avg income 1999: $" + numberFormat(1000*(d.avg_income_1999)) + "

" + "

Avg income 2014: $" + numberFormat(d.avg_income_2014) + "

" + "

Income growth, 1999-2014: " + numberFormatDetailed(d.income_growth_9914) + "% per year

" ) .style("left", (d3.event.pageX - 25) + "px") .style("top", (d3.event.pageY - 140) + "px") .transition() .duration(250) .style("display", "block") .style("opacity", 0.95); if (mouseX > (0.6*width)) { tooltip .style("left", (d3.event.pageX - 200) + "px") } }) .on("mouseout", function(d) { d3.select(".tooltip") .transition() .duration(250) .style("opacity", 0) .style("display", "none"); d3.select(this) .style("fill","#00a1ce") .style("opacity",0.6); d3.selectAll(".scatter") .style("fill","#ddd"); d3.selectAll("." + selectedVariable) .style("fill","#00a1ce"); }); d3.select(".legend") .remove(); legend = svg.append("g") .attr("class", "legend") .attr("transform", "translate(" + (width - 50) + "," + (height - 20) + ")") .selectAll("g") .data([1e6, 5e6]) .enter().append("g"); legend.append("circle") .attr("cy", function(d) { return -20*(Math.pow(((d)/1000000/3.14),0.5));}) .attr("r", function(d) { return 20*(Math.pow(((d)/1000000/3.14),0.5));}); legend.append("text") .attr("y", function(d) { return -40*(Math.pow(((d)/1000000/3.14),0.5));}) .attr("dy", "1.3em") .text(d3.format(".1s")); legend.append("text") .attr("dy", "-60px") .text("Total employment"); } }); function highlight() { selectedVariable = d3.select("#selectMenu").property("value"); d3.selectAll(".scatter") .transition() .style("fill","#ddd"); d3.selectAll("." + selectedVariable) .transition() .style("fill","#00a1ce"); }