A simplified version of my Top 10 Baby names since 1880 project looking only at the main chart
Built with blockbuilder.org
<!DOCTYPE html>
<meta charset="utf-8">
<!-- Google fonts -->
<link href='//fonts.googleapis.com/css?family=Open+Sans:300' rel='stylesheet' type='text/css'>
<!-- D3 -->
<script src="//d3js.org/d3.v3.min.js"></script>
<!-- Data -->
<script src="girl_names_us.js"></script>
<!-- Styling -->
<style>
body {
font-family: 'Open Sans', sans-serif;
font-size: 11px;
font-weight: 300;
fill: #4A4A4A;
}
#chart{
padding: 30px 20px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.x.axis path, .y.axis path {
display: none;
}
.x.axis text, .y.axis text {
font: 10px;
}
.line {
fill: none;
}
.popUpName text {
text-anchor: middle;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
}
.voronoi path {
fill: none;
pointer-events: all;
}
</style>
<body>
<div id="chart"></div>
<script src="babynames.js"></script>
</body>
//Brush is the higher focus chart, All is the smaller context chart
var margin = {top: 20, right: 30, bottom: 30, left: 50},
width = document.body.clientWidth - margin.left - margin.right - 10,
height = 500 - margin.top - margin.bottom;
var startYear = 1970,
endYear = 2014,
yearRange = endYear - startYear;
//Stroke width per max position
var strokeWidth = [12,8,8,6,6,4,4,2,2,2];
//////////////////////////////////////////////////////////////
/////////////////////////// Girls ////////////////////////////
//////////////////////////////////////////////////////////////
allGirlNames = [];
namesByID = [];
girls.forEach(function(d,i) {
allGirlNames[i] = d.name;
namesByID[d.name] = i;
});
var color = d3.scale.ordinal()
.range(["#FFC600", "#FEC606", "#FEC60B", "#FDC710", "#FDC716", "#FCC61B", "#FCC61F", "#FCC523", "#FBC427",
"#FBC22B", "#FBC02D", "#FBBD2F", "#FBBA31", "#FBB632", "#FBB132", "#FCAC31", "#FCA730", "#FDA12F", "#FD9B2D",
"#FE952C", "#FE8F2A", "#FF8929", "#FF8428", "#FF7E27", "#FF7927", "#FF7527", "#FF7128", "#FE6E29", "#FE6A2B",
"#FD682D", "#FC652F", "#FB6330", "#FA6032", "#F95E33", "#F85C34", "#F65A34", "#F55733", "#F35432", "#F15230",
"#F04F2D", "#EE4B2A", "#EC4827", "#EA4524", "#E84221", "#E63E1F", "#E43B1D", "#E2381C", "#E0351C", "#DD321E",
"#DB3020", "#D92E25", "#D62C2B", "#D42A31", "#D22939", "#CF2841", "#CD274A", "#CB2754", "#C8275D", "#C62866",
"#C4296F", "#C22A77", "#BF2C7F", "#BD2E86", "#BB308C", "#B93391", "#B73596", "#B5389A", "#B33B9D", "#B13EA0",
"#AE41A2", "#AC43A3", "#A946A4", "#A648A4", "#A349A4", "#9F4AA3", "#9B4BA2", "#974BA1", "#934B9F", "#8E4A9D",
"#8A499A", "#854897", "#804795", "#7B4692", "#76448E", "#71438B", "#6C4188"])
.domain(allGirlNames);
//////////////////////////////////////////////////////////////
///////////////////// Scales & Axes //////////////////////////
//////////////////////////////////////////////////////////////
var xScale = d3.scale.linear().domain([startYear, endYear]).range([0, width]),
yScale= d3.scale.linear().domain([0.5,10.5]).range([0, height]);
var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickFormat(d3.format("d")).tickSize(0),
yAxis = d3.svg.axis().scale(yScale).orient("left").tickSize(0);
var line = d3.svg.line()
.interpolate("monotone") //Slight rounding without too much deviation
.x(function(d) { return xScale(d.year); })
.y(function(d) { return yScale(d.position); });
//////////////////////////////////////////////////////////////
//////////////////////// Create chart ////////////////////////
//////////////////////////////////////////////////////////////
//Create focus SVG
var focus = 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 + ")");
//Append clippath to focus chart
focus.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
//Append x axis to focus chart
focus.append("g")
.attr("class", "x axis")
.style("font-size", 13)
.attr("transform", "translate(0," + (height + 9) + ")")
.call(xAxis);
//Append y axis to focus chart
focus.append("g")
.attr("class", "y axis")
.attr("transform", "translate(-10,0)")
.call(yAxis)
.append("text")
.attr("class", "titles")
.attr("transform", "rotate(-90)")
.attr("x", -(height/2))
.attr("y", -35)
.attr("dy", ".71em")
.style("font-size", 14)
.style("text-anchor", "middle")
.text("Position in Top 10");
//////////////////////////////////////////////////////////////
///////////////////////// Voronoi ////////////////////////////
//////////////////////////////////////////////////////////////
//Create a flat data version for the Voronoi
/*************************************************************/
var flatData = [];
for (k in girls) {
var k_data = girls[k];
k_data.values.forEach(function(d) {
if (d.position <= 10) flatData.push({name: k_data.name, year: d.year, position: d.position});
});
}//for k
var maxPosition = d3.nest()
.key(function(d) { return d.name; })
.rollup(function(d) {return d3.min(d, function(g) {return g.position;});})
.entries(flatData);
var nestedFlatData = d3.nest().key(function(d) { return d.name; }).entries(flatData);
/*************************************************************/
//Initiate the voronoi function
var voronoi = d3.geom.voronoi()
.x(function(d) { return xScale(d.year); })
.y(function(d) { return yScale(d.position); })
.clipExtent([[-margin.left, -margin.top], [width + margin.right, height + margin.bottom]]);
//Initiate the voronoi group element
var voronoiGroup = focus.append("g")
.attr("class", "voronoi");
voronoiGroup.selectAll("path")
.data(voronoi(flatData.filter(function(d) {return d.year >= xScale.domain()[0] & d.year <= xScale.domain()[1]; })))
.enter().append("path")
.attr("d", function(d) { return "M" + d.join("L") + "Z"; })
.datum(function(d) { return d.point; })
.attr("class", "voronoiCells")
.on("mouseover", mouseover)
.on("mouseout", mouseout);
//Voronoi mouseover and mouseout functions
function mouseover(d) {
focus.selectAll(".focus").style("opacity", 0.1);
focus.selectAll("."+d.name).style("opacity", 0.8);
//Move the tooltip to the front
d3.select(".popUpName").moveToFront();
//Change position, size of circle and text of tooltip
popUpName.attr("transform", "translate(" + xScale(d.year) + "," + yScale(d.position) + ")");
var circleSize = parseInt(d3.selectAll(".focus." + d.name).selectAll(".line").style("stroke-width"));
popUpName.select(".tooltipCircle").style("fill", color(d.name)).attr("r", circleSize);
popUpName.select("text").text(d.name);
}//mouseover
function mouseout(d) {
focus.selectAll(".focus").style("opacity", 0.7);
popUpName.attr("transform", "translate(-100,-100)");
}//mouseout
//Move selected element to the front
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
//////////////////////////////////////////////////////////////
//////////////////////// Create lines ////////////////////////
//////////////////////////////////////////////////////////////
var focusData = focus.selectAll(".focus")
.data(girls)
.enter().append("g")
.attr("class", function(d) {return "focus " + d.name ;})
.append("path")
.attr("class", "line")
.attr("clip-path", "url(#clip)")
.style("pointer-events", "none")
.style("stroke-linejoin", "round")
.style("opacity", 0)
.attr("d", function(d) { return line(d.values); })
.style("stroke-width", function(d) {return strokeWidth[maxPosition[namesByID[d.name]].values - 1]; })
.style("stroke", function(d) {return color(d.name); })
.transition().duration(750).delay(500)
.style("opacity", 0.7);
//////////////////////////////////////////////////////////////
//////////////////////// Tooltip /////////////////////////////
//////////////////////////////////////////////////////////////
var popUpName = focus.append("g")
.attr("transform", "translate(-100,-100)")
.attr("class", "popUpName")
.style("pointer-events", "none");
popUpName.append("circle")
.attr("class", "tooltipCircle")
.attr("r", 3.5);
popUpName.append("text")
.style("font-size", 12)
.attr("class", "titles")
.attr("y", -15);