//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);