// 2nd chart var w = 1000, h = 3000; //undefined Farouq var teams = [ "ATL","BOS","BKN","CHA","CHI", "CLE","DAL","DEN","DET","GSW", "HOU","IND","LAC","LAL","MEM", "MIA","MIL","MIN","NOP","NYK", "OKC","ORL","PHI","PHX","POR", "SAC","SAS","TOR","UTA","WAS" ] var svg = d3.select("#chart").append("svg:svg") .attr("width",w) .attr("height",h) .style("background-color","white"); var vis = svg.append("g").attr("transform", "translate(0,60)") var innerRadius = Math.min(w, h) * .41, outerRadius = innerRadius * 1.1; var texts = vis.append("g").attr("transform","translate(420,0)"); texts.append("rect").attr("width",354).attr("height",130).style("fill","#ccc").style("opacity",0.5).attr("x",-8) var player1 = texts.append("text").attr("y",40).attr("class","playerName"); var player2 = texts.append("text").attr("y",60).attr("class","playerName"); var player3 = texts.append("text").attr("y",80).attr("class","playerName"); var player4 = texts.append("text").attr("y",100).attr("class","playerName"); var player5 = texts.append("text").attr("y",120).attr("class","playerName"); var detailOff = texts.append("text").attr("x",160).attr("y",20).attr("class","detailText"); var detailDef = texts.append("text").attr("x",160).attr("y",40).attr("class","detailText"); var detailMin = texts.append("text").attr("x",160).attr("y",60).attr("class","detailText"); var detailEfg = texts.append("text").attr("x",160).attr("y",80).attr("class","detailText"); var detailDefReb = texts.append("text").attr("x",160).attr("y",100).attr("class","detailText"); var detailOffReb = texts.append("text").attr("x",160).attr("y",120).attr("class","detailText"); var teamName = texts.append("text").attr("y",20).attr("class","teamHeader"); var toggles = svg.append("g").attr("transform", "translate(0,24)"); function basicSort(accessor) { return function(a,b) { var aScalar = a.stats[accessor]; var bScalar = b.stats[accessor]; return d3.descending(aScalar,bScalar); } } function advancedSort(a,b) { var aTeam = teams.indexOf(a.team); var bTeam = teams.indexOf(b.team); return d3.ascending(aTeam,bTeam) || d3.descending(+a.stats.min,+b.stats.min); } toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(33,3)") toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(93,3)") toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(153,3)") toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(230,3)") toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(270,3)") toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(305,3)") toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(340,3)"); toggles.append("polygon").attr("class","sortarrow").attr("points","0,0 10,0 5,10").attr("transform", "translate(375,3)"); toggles.append("text").text("Group by Team").style("font-size","12px").attr("y",12).attr("x",404).style("fill","black") toggles.append("text").text("Off.").attr("y",12).style("fill","black").style("font-size","12px").attr("x",5) toggles.append("text").text("Def.").attr("y",12).style("fill","black").style("font-size","12px").attr("x",65) toggles.append("text").text("Net").attr("y",12).style("fill","black").style("font-size","12px").attr("x",125) var toggleData = [ {"x":0, "width":50,"sort":basicSort('off_rating')}, {"x":60, "width":50,"sort":basicSort('def_rating')}, {"x":120,"width":50,"sort":basicSort('net_rating')}, {"x":220,"width":30,"sort":basicSort('min')}, {"x":260,"width":30,"sort":basicSort('efg_pct')}, {"x":295,"width":30,"sort":basicSort('def_reb_pct')}, {"x":330,"width":30,"sort":basicSort('off_reb_pct')}, {"x":365,"width":30,"sort":basicSort('reb_pct')}, {"x":400,"width":90,"sort":advancedSort,"offsetTeams":true} ] toggles.selectAll(".toggleButton").data(toggleData).enter() .append("rect").attr({ "height":16, "width":function(d) { return d.width }, "ry":4, "rx":4, "x":function(d) { return d.x } }).on("click", function(td) { vis.selectAll(".unit").sort(td.sort) .transition().duration(300) .delay(function(d,i) { return i * 3 }) .attr("transform", function(d,i) { var teamY = teams.indexOf(d.team) if (td.offsetTeams == undefined) { teamY = 0; } return "translate(0," + (i * 11 + 5 * teamY) + ")"; }); bindTexts(); }).style("opacity",0.4) .on("mouseover",function() { d3.select(this).style("fill","red"); }).on("mouseout",function() { d3.select(this).style("fill","black"); }); var labels = svg.append("g").attr("transform","translate(0,54)"); labels.append("text").text("points").attr("x",0).style("font-size",11); labels.append("text").text("scored/").attr("x",32).style("font-size",11).style("fill","#04BF9D"); labels.append("text").text("allowed").attr("x",72).style("font-size",11).style("fill","#F53D54"); labels.append("text").text("per 100 poss.").attr("x",112).style("font-size",11); labels.append("text").text("min").attr("x",226).style("font-size",11); labels.append("text").text("eFG%").attr("x",266).style("font-size",11); labels.append("text").text("DR%").attr("x",302).style("font-size",11); labels.append("text").text("OR%").attr("x",336).style("font-size",11); labels.append("text").text("R%").attr("x",376).style("font-size",11); var ratingScale = d3.scale.linear().domain([65,120]).range([0,160]); var timeScale = d3.scale.linear().domain([0,2000]).range([0,70]); var shootScale = d3.scale.linear().domain([30.0,70.0]).range([0,30]); var defRebScale = d3.scale.linear().domain([50.0,90.0]).range([0,30]); var offRebScale = d3.scale.linear().domain([10.0,50.0]).range([0,30]); var rebScale = d3.scale.linear().domain([30.0,60.0]).range([0,30]); d3.json('data.json', function(data) { var unit_g = vis.selectAll(".unit").data(data).enter().append("g").attr("class","unit") .attr("transform",function(d,i) { return "translate(0," + (i * 11) + ")"; }) unit_g.append("rect").attr("height",10).attr("width", function(d) { var rating = +d.stats.off_rating; return ratingScale(rating); }) .style("fill","#04BF9D") unit_g.append("rect").attr("height",10).attr("width", function(d) { var rating = +d.stats.def_rating; return ratingScale(rating); }) .style("fill","#565655") unit_g.append("rect").attr("height",10) .attr("width", function(d) { var def_rating = +d.stats.def_rating; var off_rating = +d.stats.off_rating; if (def_rating > off_rating) { return ratingScale(def_rating)-ratingScale(off_rating); } else { return 0; } }) .attr("x", function(d) { var off_rating = +d.stats.off_rating; return ratingScale(off_rating); }) .style("fill","#F53D54") .style("opacity",1) unit_g.append("rect").attr("x",210).attr("height",2).attr("y",3).attr("width", function(d) { return timeScale(d.stats.min) }).attr("fill", "#222"); unit_g.append("rect").attr("x",265).attr("height",10).attr("width", function(d) { return shootScale(d.stats.efg_pct); }).attr("fill", "#00A19A"); unit_g.append("rect").attr("x",300).attr("height",10).attr("width", function(d) { return defRebScale(d.stats.def_reb_pct); }).attr("fill", "#00A19A"); unit_g.append("rect").attr("x",335).attr("height",10).attr("width", function(d) { return offRebScale(d.stats.off_reb_pct); }).attr("fill", "#00A19A"); unit_g.append("rect").attr("x",370).attr("height",10).attr("width", function(d) { return rebScale(d.stats.reb_pct); }).attr("fill", "#00A19A"); unit_g.append("text").attr("font-size", "11px").attr("fill","#ccc").attr("y",9).text(function(d) { return d.team; }).attr("x",3); var interactives = unit_g.append("rect").attr("class","unitInteractives").attr("height",10).attr("width", 412) .style("fill","#ccc").style("opacity",0) .on("mouseout", function(d) { d3.select(this).style("opacity",0.0); }); bindTexts(); }) function bindTexts() { d3.selectAll(".unitInteractives").on("mouseover", function(d,i) { d3.select(this).style("opacity",0.5); player1.text(d.players[0][1] + " " + d.players[0][0]); player2.text(d.players[1][1] + " " + d.players[1][0]); player3.text(d.players[2][1] + " " + d.players[2][0]); player4.text(d.players[3][1] + " " + d.players[3][0]); player5.text(d.players[4][1] + " " + d.players[4][0]); teamName.text(d.team + " Lineup:"); detailOff.text("scores " + d.stats.off_rating + " points/100 pos."); detailDef.text("allows " + d.stats.def_rating + " points/100 pos."); detailMin.text("played " + d.stats.min + " minutes"); detailEfg.text(d.stats.efg_pct + " effective field goal %"); detailDefReb.text(d.stats.def_reb_pct + " defensive rebounding"); detailOffReb.text(d.stats.off_reb_pct + " offensive rebounding"); var y = i * 11; texts.attr("transform", "translate(420," + y + ")"); }) }