D3
OG
Old school D3 from simpler times
All examples
By author
By category
About
saraquigley
Full window
Github gist
Multiple Majors Leaderboard
<!DOCTYPE html> <meta charset="utf-8"> <link href='https://fonts.googleapis.com/css?family=Lato:400,900,700,300,200' rel='stylesheet' type='text/css'> <style> body { font-size: 10px; font-family: 'Lato', "Helvetica Neue", Helvetica, Arial, sans-serif; } .comment { font-family: 'Lato', "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12pt; font-weight: 300; margin: 0.5em 160px 1em 160px; text-align: center; } .x.axis path { display: none; } .x.axis line { fill: none; stroke: #bbb; shape-rendering: crispEdges; } .y.axis path { fill: none; } .y.axis line { fill: none; stroke: #eeeeee; shape-rendering: crispEdges; } #toggle { margin: 0.5em 160px 1em 160px; font-family: 'Lato', "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12pt; font-weight: 400; text-align: center; } #header { font-family: 'Lato', sans-serif; font-size: 32px; font-weight: 300; /*letter-spacing: -2px;*/ padding: 0em 1em 0 0; text-rendering: optimizeLegibility; text-align: center; } #copyright { text-align: center; font-family: 'Lato', "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 12pt; font-weight: 300; } </style> <body> <div class="comment">This trend leaderboard ranks majors by the count or percent of undergraduate multiple majors at UC Berkeley over time and can serve as a summary of 10 years of double/triple major matrices found <a href='index-matrix.html' target='_blank'>here</a>. For a scrollable explanation, please click <a href='index.html' target='_blank'>here</a>. <span class='hint'> Hint: Hover over a major name to see its ranking over time. Click on the major name to toggle showing/hiding it. </span></div> <div> <form id="toggle" style="opacity:1;"> <label><input type="radio" name="mode" id="count" value="count" checked>Rank by Count</label> <label><input type="radio" name="mode" id="percent" value="percent" >Rank by Percent</label> <!-- <button id="showall">Show All</button> --> </form> </div> <div id="bump"></div> <div id="copyright"></div> <script src="https://d3js.org/d3.v3.js"></script> <script> var margin2 = {top: 110, right: 200, bottom: 0, left: 200}, width2 = 1260 - margin2.left - margin2.right, height2 = 1000 - margin2.top - margin2.bottom; var pctFormat = d3.format(",.1%"); var speed = 600; var x2 = d3.scale.ordinal() .rangeRoundBands([0, width2],1); var y2 = d3.scale.ordinal() .rangeRoundBands([800, -20], .1); var xAxis = d3.svg.axis() .scale(x2) .tickSize(6) .orient("top"); var yAxis = d3.svg.axis() .scale(y2) .tickSize(-width2) .tickValues("") .tickPadding(10) .orient("left"); var line = d3.svg.line() .x(function(d) { return x2(d.termyear); }) .y(function(d) { return mode === "percent" ? y2(d.pct_rank) + y2.rangeBand()/2 : y2(d.count_rank) + y2.rangeBand()/2; }) .interpolate("linear"); var svg = d3.select('#bump').append("svg") .attr("width", width2 + margin2.left + margin2.right) .attr("height", height2 + margin2.top + margin2.bottom) .style("margin-left", (window.innerWidth - (width2 + margin2.left + margin2.right))/2) .style("font-size",14) .append("g") .attr("transform", "translate(" + margin2.left + "," + margin2.top + ")"); var clip = svg.append("clipPath") .attr("id", "clip") .append("rect") .attr("width", 0) .attr("height", height2); // .on('active', function(i){ // return; // }); // var color = d3.scale.category20b(); var c = d3.scale.ordinal().domain(d3.range(0,8)).range(["#5254a3","#8ca252","#ad494a","#0868ac","#bd9e39","#01665e","#8c510a","#a55194","#d94801","#6b6ecf","#e7ba52","#d6616b","#b5cf6b","#bf812d","#2b8cbe"]); var termyears2 = ["2005 Spring", "2005 Fall", "2006 Spring", "2006 Fall", "2007 Spring", "2007 Fall", "2008 Spring", "2008 Fall", "2009 Spring", "2009 Fall", "2010 Spring", "2010 Fall", "2011 Spring", "2011 Fall", "2012 Spring", "2012 Fall", "2013 Spring", "2013 Fall", "2014 Spring", "2014 Fall", "2015 Spring", "2015 Fall"]; var selectedPath = []; var mode="percent"; d3.json("data.json", function(error, data) { y2.domain(d3.range(1,52).reverse()); x2.domain(termyears2); xAxis.tickValues(termyears2).tickFormat(function(d,i) { // return d.substring(d.length-6, d.length) === "Spring" ? "" : d.substring(0,d.length-5); return d.substring(d.length-6, d.length) === "Spring" ? d.substring(0,4) + " Spring" : d.substring(0,4) + " Fall"; }); svg.append("g") .attr("class", "y axis") .call(yAxis); svg.append("g") .attr("class", "x axis") .attr("transform", "translate(0,-20)") .call(xAxis); d3.selectAll(".x.axis text").attr("transform","translate(12,-10)rotate(300)") .style("text-anchor","start") .style("fill", function(d,i) {return i % 2 > 0 ? "#ccc" : "#ddd";}); var club = svg.selectAll(".club") .data(data) .enter().append("g") .attr("class", "club") .style("opacity",0.75); var path = club.append("path") .attr("class", "line") .style("stroke", function(d,i) { return c(i); // return c(d.values[d.values.length-1].group); }) .style("stroke-width", 4) .style("fill","none") .style("stroke-opacity",0.75) .attr("d", function(d) { return line(d.values); }) .on("click", function(d) { d3.select(this).classed("hl",true); } ); var circleStart = club.selectAll("circle") .data(function(d) {return d.values;}) .enter() .append("circle") .attr("cx", function(d) { return x2(d.termyear); }) .attr("cy", function(d) { return y2(d.pct_rank) + y2.rangeBand()/2; }) .style("fill", function(d,i) { // var qq = club.filter(function(path) {return path.key === d.name; }); var indice = club.data().map(function(d,i) {return {key: d.key, index: i};}); var qq = indice.filter(function(r) {return r.key === d.name;}); return c(qq[0].index); // return c(qq.datum().values[qq.datum().values.length-1].group); // this is the cluster/group }) .style("fill-opacity",0.75) .attr("r", 4); circleStart.append("title") .text(function(d) {return mode === "percent" ? "approximately " + pctFormat(d.pct) : "approximately " + d.majors;}); var start_label = club.append("text") .attr("transform", function(d) { return "translate(" + x2(d.values[0].termyear) + "," + (y2(d.values[0].pct_rank) + y2.rangeBand()/2) + ")"; }) .attr("x", -8) .attr("dy", ".31em") .on("mouseover", function (d) { // console.log('selectedPath', selectedPath) club.filter(function(path) { return path.key != d.key; }).style("opacity",0.05); club.filter(function(path) { return path.key === d.key; }).style("opacity",0.75); club.filter(function(path) { return selectedPath.indexOf(path.key) >= 0; }).style("opacity",0.75); }) .on("mouseout", function (d) { club.filter(function(path) { return path.key === d.key; }).style("opacity",0.05); if(selectedPath.length == 0) {club.style("opacity",0.75);} else {club.filter(function(path) { return selectedPath.indexOf(path.key) >= 0; }).style("opacity",0.75); } }) .on("click", function (d) { var ik = selectedPath.indexOf(d.key); if( ik >= 0) { selectedPath.splice(ik, 1); club.filter(function(path) {return path.key === d.key; }).style("opacity",0.05); } else { selectedPath.push(d.key); club.filter(function(path) {return path.key === d.key; }).style("opacity",0.75); club.filter(function(path) {return path.key != d.key; }).style("opacity",0.05); } club.filter(function(path) { return selectedPath.indexOf(path.key) >= 0; }).style("opacity",0.75); }) .style("cursor","pointer") .style("fill", function(d,i) { return d.values[0].termyear === termyears2[0] ? c(i) : "#525252"; // return d.values[0].termyear === termyears2[0] ? c(d.values[d.values.length-1].group) : "#525252"; }) // .style("font-weight", "bold") .style("text-anchor","end") .text(function(d) { return mode === "percent" ? d.key + " " + "#"+ d.values[0].pct_rank : d.key + " " + "#"+ d.values[0].count_rank; }); var end_label = club.append("text") .attr("transform", function(d) { return "translate(" + x2(d.values[d.values.length-1].termyear) + "," + (y2(d.values[d.values.length-1].pct_rank) + y2.rangeBand()/2) + ")"; }) .attr("x", 8) .attr("dy", ".31em") .on("mouseover", function (d) { // console.log('selectedPath', selectedPath) club.filter(function(path) { return path.key != d.key; }).style("opacity",0.05); club.filter(function(path) { return path.key === d.key; }).style("opacity",0.75); club.filter(function(path) { return selectedPath.indexOf(path.key) >= 0; }).style("opacity",0.75); }) .on("mouseout", function (d) { club.filter(function(path) { return path.key === d.key; }).style("opacity",0.05); if(selectedPath.length == 0) {club.style("opacity",0.75);} else {club.filter(function(path) { return selectedPath.indexOf(path.key) >= 0; }).style("opacity",0.75); } }) .on("click", function (d) { var ik = selectedPath.indexOf(d.key); if( ik >= 0) { selectedPath.splice(ik, 1); club.filter(function(path) {return path.key === d.key; }).style("opacity",0.05); } else { selectedPath.push(d.key); club.filter(function(path) {return path.key === d.key; }).style("opacity",0.75); club.filter(function(path) {return path.key != d.key; }).style("opacity",0.05); } club.filter(function(path) { return selectedPath.indexOf(path.key) >= 0; }).style("opacity",0.75); }) .style("cursor","pointer") .style("fill", function(d,i) { return d.values[d.values.length-1].termyear === termyears2[termyears2.length-1] ? c(i) : "#525252"; // return d.values[d.values.length-1].termyear === termyears2[termyears2.length-1] ? c(d.values[d.values.length-1].group) : "#525252"; }) // .style("font-weight", "bold") .text(function(d) { return mode === "percent" ? "#"+ d.values[d.values.length-1].pct_rank + " " + d.key : "#"+ d.values[d.values.length-1].count_rank + " " + d.key; }); function load(a) { // choose whether to load counts or percents mode = a; path.transition().duration(5000).attr("d", function(d) { return line(d.values); }); circleStart.transition().duration(5000).attr("cy", function(d) { return mode === "percent" ? y2(d.pct_rank) + y2.rangeBand()/2 : y2(d.count_rank) + y2.rangeBand()/2; }); circleStart.selectAll("title").text(function(d) {return mode === "percent" ? "approximately " + pctFormat(d.pct) : "approximately " + d.majors;}); start_label.transition().duration(5000).attr("transform", function(d) { return mode === "percent" ? "translate(" + x2(d.values[0].termyear) + "," + (y2(d.values[0].pct_rank) + y2.rangeBand()/2) + ")" : "translate(" + x2(d.values[0].termyear) + "," + (y2(d.values[0].count_rank) + y2.rangeBand()/2) + ")"; }) .text(function(d) { return mode === "percent" ? d.key + " " + "#"+ d.values[0].pct_rank : d.key + " " + "#"+ d.values[0].count_rank; }); end_label.transition().duration(5000).attr("transform", function(d) { return mode === "percent" ? "translate(" + x2(d.values[d.values.length-1].termyear) + "," + (y2(d.values[d.values.length-1].pct_rank) + y2.rangeBand()/2) + ")" : "translate(" + x2(d.values[d.values.length-1].termyear) + "," + (y2(d.values[d.values.length-1].count_rank) + y2.rangeBand()/2) + ")"; }) .text(function(d) { return mode === "percent" ? "#"+ d.values[d.values.length-1].pct_rank + " " + d.key : "#"+ d.values[d.values.length-1].count_rank + " " + d.key; }); } d3.selectAll("form#toggle label input").on("change", function() { load(this.value); }); d3.select("#showall").on("click", function() { selectedPath = []; club.style("opacity",0.75); } ); selectedPath = ["Computer Science","Applied Mathematics","Statistics", "Physics"]; selectedPath.forEach(function(d) { club.filter(function(path) { return path.key != d.key; }).style("opacity",0.05); club.filter(function(path) { return path.key === d.key; }).style("opacity",0.75); club.filter(function(path) { return selectedPath.indexOf(path.key) >= 0; }).style("opacity",0.75); }); load("count"); }); </script> </body> </html>
https://d3js.org/d3.v3.js