SELECT *, ROW_NUMBER() OVER (ORDER BY distance DESC) AS id FROM benn.home_run_distance WHERE distance != 0 AND apex != 0 AND hr_type IN ('ND','ND/L','PL','PL/L','JE','JE/L') ORDER BY distance DESC -- LIMIT 1000
SELECT *, ROW_NUMBER() OVER (ORDER BY distance DESC) AS id FROM benn.home_run_distance WHERE distance != 0 AND apex != 0 AND hr_type IN ('ND','ND/L','PL','PL/L','JE','JE/L') ORDER BY distance DESC -- LIMIT 1000
<style> h1 { text-align: center; } .description p, .source p { max-width: 600px; margin: 0 auto; text-align: center; } .players { max-width: 600px; margin: 0 auto; text-align: center; color: grey; cursor: pointer; margin-top: 0px; } .hide { display: none; } a { color: grey; } .player-active { text-decoration: underline; } .btn { color: #e6834e; background-color: white; border: 1px Solid #e6834e; height:25px; width: 75px; cursor: pointer; padding: 2px 0px 0px 0px; margin: 0px 10px 0px; border-radius: 5px; vertical-align: baseline; text-align: center; margin-bottom: 20px; margin-top:20px; } .btn.active, #next-btn { background-color: #e6834e; color: white; } .btn:hover { border: 1px solid #FFA778; color: #FFA778; } .btn.active { background-color: #e6834e; color: white; } .btn.active:hover, #next-btn:hover { background-color: #ef9c69; border: 1px solid #ef9c69; } .axis path, .axis line { fill: none; stroke: black; shape-rendering: crispEdges; } .axis path { display: none; } .hr-dot { stroke: red; fill: none; } .major { stroke: black; } .minor { stroke: #ccc; } .none { stroke: none; } .speed-bars, .apex-bars, .dist-bars { fill: grey; opacity: .8; } .legend-bar-text, .legend-bars-text { font-style: italic; fill: grey; } .legend-circle-text { font-style: italic; fill: red; } .stage-title { text-anchor: middle; font-size: 20px; fill: black; } </style> <h1>Mapping the Longest Home Runs</h1> <div class="description"> <p> Over 40,000 home runs have been hit in the last seven and a half MLB seasons&mdash;but they weren't all hit equally. Click Start to see how tonight's Home Run Derby participants stack up. </p> </div> <div id="buttons" style="text-align:center;"></div> <div class="players hide"> <p> <span class="player-selector player-active" id="all">All 2014 HR Derby Participants</span></br> <span class="player-selector" id="jones">Jones</span> | <span class="player-selector" id="bautista">Bautista</span> | <span class="player-selector" id="donaldson">Donaldson</span> | <span class="player-selector" id="frazier">Frazier</span> | <span class="player-selector" id="cespedes">Cespedes</span></br> <span class="player-selector" id="dozier">Dozier</span> | <span class="player-selector" id="stanton">Stanton</span> | <span class="player-selector" id="morneau">Morneau</span> | <span class="player-selector" id="tulowitzki">Tulowitzki</span> | <span class="player-selector" id="puig">Puig</span></br> <span class="player-selector" id="longest">100 longest home runs since 2006</span> </p> </div> <div id="graphicWrapper" style="text-align:center"> <div id="chart"></div> </div> <div class="source"> <p>Source: <a target="_blank" href="http://www.hittrackeronline.com/index.php">ESPN Home Run Tracker</a></p> </div> <script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.6.0/underscore-min.js"></script> <script src="//cdnjs.cloudflare.com/ajax/libs/crossfilter/1.3.7/crossfilter.min.js"></script> <script src="https://cdn.rawgit.com/mbostock/d3/master/lib/colorbrewer/colorbrewer.js"></script> <script> var fullWidth = Math.max(Math.min($(window).width(),750),500); var full = dataset.content, homeRuns = full.length, horAngleArray = [0,22.5,45,67.5,90], elevArray = [0,10,20,30,40,50], distanceArcs = [350,400,450,500]; var cross = crossfilter(full), speed = cross.dimension(function(d) { return d.speed; }), speeds = speed.group(function(d) { return Math.floor(d); }), speedDist = speeds.top(homeRuns), speedRange = d3.extent(_.pluck(speedDist,"key")), speedMaxCount = d3.max(_.pluck(speedDist,"value")), elevAngle = cross.dimension(function(d) { return d.elev_angle; }), elevAngles = elevAngle.group(function(d) { return Math.floor(d); }), elevAngleDist = elevAngles.top(homeRuns), elevRange = d3.extent(_.pluck(elevAngleDist,"key")), elevCountRange = d3.extent(_.pluck(elevAngleDist,"value")), elevMaxCount = d3.max(_.pluck(elevAngleDist,"value")), apex = cross.dimension(function(d) { return d.apex; }), apexes = apex.group(function(d) { return Math.floor(d/2)*2; }), apexDist = apexes.top(homeRuns), apexRange = d3.extent(_.pluck(apexDist,"key")), apexMaxCount = d3.max(_.pluck(apexDist,"value")), distance = cross.dimension(function(d) { return d.distance; }), distances = distance.group(function(d) { return Math.floor(d/2)*2; }), distanceDist = distances.top(homeRuns), distanceRange = d3.extent(_.pluck(distanceDist,"key")), distanceMaxCount = d3.max(_.pluck(distanceDist,"value")), horAngle = cross.dimension(function(d) { return d.horiz_angle; }), horAngles = horAngle.group(function(d) { return Math.floor(d); }), horAngleDist = horAngles.top(homeRuns), horRange = d3.extent(_.pluck(horAngleDist,"key")), horCountRange = d3.extent(_.pluck(horAngleDist,"value")), horMaxCount = d3.max(_.pluck(horAngleDist,"value")), hitter = cross.dimension(function(d) { return d.hitter; }), longestCross = cross.dimension(function(d) { return +d.id; }); if (fullWidth < 750) { margin = {top: 20, right: 20, bottom: 20, left: 20} } else { margin = {top: 20, right: 100, bottom: 20, left: 100} } var width = fullWidth - margin.left - margin.right, height = 500 - margin.top - margin.bottom; var start = d3.select("#buttons").append("button") .attr("class","btn") .attr("id","start") .attr("x",width/2) .attr("y",height/2) .attr("height",100) .attr("width",100) .text("Start") 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 speedScale = d3.scale.linear() .domain([80,130]) .range([0, width/2 + 100]); var distanceScale = d3.scale.linear() .domain([0,520]) .range([0,width]); var distanceScale2 = d3.scale.linear() .domain([0,520]) .range([0,height]); var apexScale = d3.scale.linear() .domain([200,0]) .range([0,height*.75]); var speedAxis = d3.svg.axis() .scale(speedScale) .tickFormat(formatSpeed) .ticks(4) .orient("bottom"); var apexAxis = d3.svg.axis() .scale(apexScale) .tickFormat(formatApex) .orient("right"); var distanceAxis = d3.svg.axis() .scale(distanceScale) .tickFormat(formatDistance) .orient("bottom"); function formatSpeed(d) { if (d === speedScale.domain()[1]) { return d + " mph"; } else { return d;} } function formatApex(d) { if (d === apexScale.domain()[0]) { return d + " feet"; } else { return d;} } function formatDistance(d) { if (d === 500) { return d + " feet"; } else { return d;} } var elevShadeScale = d3.scale.quantize() .domain(d3.extent(elevCountRange)) .range(colorbrewer.Blues[9]); var horShadeScale = d3.scale.quantize() .domain(d3.extent(horCountRange)) .range(colorbrewer.Blues[9]); var elevStep = ((elevShadeScale.domain()[1] - elevShadeScale.domain()[0])/9); var horStep = ((horShadeScale.domain()[1] - horShadeScale.domain()[0])/9); var eps = d3.round(100*elevStep/homeRuns); // var hps = d3.round(horStep/homeRuns,3)*100; var hps = 0.2; var elevLabelRange = [0,eps*1,eps*2,eps*3,eps*4,eps*5,eps*6,eps*7,eps*8] // var horLabelRange = [0,hps*1,hps*2,hps*3,hps*4,hps*5,hps*6,hps*7,hps*8] var horLabelRange = [0,.2,.4,.8,"1.0",1.2,1.4,1.6,1.8] var PLAYER = "All participants' HRs" var STAGE = 0; var stage1Caption = "<div style='width: 250px;'>" + "<p class='stage-title'>The speed off the bat</p>" + "<p>Home run hitters generate a ton of power at the plate, and about 75% home runs come off" + " the bat at over 100 miles per hour. The longest home runs are often moving at even higher speeds," + " sometimes in excess of 120 mph." + "</p></div>"; var stage2Caption = "<div style='width: 250px;'>" + "<p class='stage-title'>The angle of elevation</p>" + "<p>Most home runs begin climbing at an angle between 20 and 40 degrees. Long home runs tend to take off" + " at angles of less than 30 degrees." + "</p></div>"; var stage3Caption = "<div style='width: 250px;'>" + "<p class='stage-title'>Too high, is it too high?</p>" + "<p>Home runs reach a wide range of heights. Some never get more than 60 feet off of the ground, while others sail" + " higher than 180 feet. The longest home runs are typically low-flying line drives." + "</p></div>"; var stage4Caption = "<div style='width: 250px;'>" + "<p class='stage-title'>How far they fly</p>" + "<p>The average home run travels about 400 feet. The longest home runs go nearly 100 feet further. Since 2006," + " one home run&mdash;a blast by the Diamondbacks' Adam Dunn in 2008&mdash;exceeded 500 feet." "</p></div>"; var stage5Caption = "<div style='width: 250px;'>" + "<p class='stage-title'>Where they land</p>" + "<p>Home runs tend to land in the seats beyond left-center and right-center field. The longest home runs, however," + " tend to be more concentrated in center field." "</p></div>"; renderInitial(); renderStage(0); function renderStage(stage,transitionTime) { if (stage == 1) { showSpeed(data,transitionTime); } if (stage == 2) { showElevAngle(data,transitionTime); } if (stage == 3) { showApex(data,transitionTime); } if (stage == 4) { showDistance(data,transitionTime); } if (stage == 5) { showHorAngle(data,transitionTime); } if (stage == 6) { renderStart(data,transitionTime); } } function flipButtons() { d3.select("#start").remove() d3.select("#buttons").append("button") .attr("class","btn") .attr("id","speed-btn") .text("Speed") d3.select("#buttons").append("button") .attr("class","btn") .attr("id","angle-btn") .text("Angle") d3.select("#buttons").append("button") .attr("class","btn") .attr("id","height-btn") .text("Height") d3.select("#buttons").append("button") .attr("class","btn") .attr("id","distance-btn") .text("Distance") d3.select("#buttons").append("button") .attr("class","btn") .attr("id","location-btn") .text("Location") d3.select("#buttons").append("button") .attr("class","btn") .attr("id","next-btn") .text("Next") } function renderInitial() { svg.append("path") .attr("class","infield") .attr("d",d3.svg.arc() .innerRadius(distanceScale(0)) .outerRadius(distanceScale(120)) .startAngle((-45) * (Math.PI/180)) .endAngle((45) * (Math.PI/180)) ) .attr("transform", "translate(" + width/2 + "," + height + ")") .style("fill","brown") .style("opacity",.2); svg.append("line") .attr("class","infield-line") .attr("x1",0) .attr("x2",width*.3) .attr("y1",height*.75) .attr("y2",height*.75) .style("stroke-width",0) .style("stroke","brown") .style("opacity",.2); svg.append("path") .attr("class","outfield") .attr("d",d3.svg.arc() .innerRadius(distanceScale(120)) .outerRadius(distanceScale(400)) .startAngle((-45) * (Math.PI/180)) .endAngle((45) * (Math.PI/180)) ) .attr("transform", "translate(" + width/2 + "," + height + ")") .style("fill","green") .style("opacity",.2); svg.append("line") .attr("class","outfield-line") .attr("x1",width*.3) .attr("x2",width) .attr("y1",height*.75) .attr("y2",height*.75) .style("stroke-width",0) .style("stroke","green") .style("opacity",.2); svg.append("g") .attr("class", "axis") .attr("id","speed-axis") .attr("transform","translate(0," + (height*.75) + ")") .style("opacity",0) .call(speedAxis) svg.append("g") .attr("class", "axis") .attr("id","apex-axis") .attr("transform", "translate(" + distanceScale(400) + ",0)") .style("opacity",0) .call(apexAxis) svg.append("g") .attr("class", "axis") .attr("id","distance-axis") .attr("transform","translate(0," + (height*.75) + ")") .style("opacity",0) .call(distanceAxis) svg.selectAll(".speed-bars") .data(speedDist) .enter().append("rect") .attr("class","speed-bars") .attr("id",function(d) { return "speed-" + d.key; }) .attr("x",function(d) { return speedScale(d.key); }) .attr("y",height*.75 - 50) .attr("height",0) .attr("width",speedScale(1) - speedScale(0)); elevAngleDist.forEach(function(d) { svg.append("path") .attr("class","elev-arc") .attr("d",d3.svg.arc() .innerRadius(distanceScale(100)) .outerRadius(distanceScale(350)) .startAngle((90 - d.key) * (Math.PI/180)) .endAngle((90 - d.key - 1) * (Math.PI/180)) ) .attr("transform", "translate(0," + height*.75 + ")") .style("fill",elevShadeScale(d.value)) .style("opacity",0); }) svg.selectAll(".apex-bars") .data(apexDist) .enter().append("rect") .attr("class","apex-bars") .attr("id",function(d) { return "apex-" + d.key; }) .attr("x",distanceScale(360)) .attr("y",function(d) { return (height*.75 - apexScale(d.key)); }) .attr("width",0) .attr("height",apexScale(0) - apexScale(2)) svg.selectAll(".dist-bars") .data(distanceDist) .enter().append("rect") .attr("class","dist-bars") .attr("id",function(d) { return "distance-" + d.key; }) .attr("x",function(d) { return distanceScale(d.key); }) .attr("y",height*.75 - 50) .attr("height",0) .attr("width",distanceScale(2) - distanceScale(0)); horAngleDist.forEach(function(d) { svg.append("path") .attr("class","hor-arc") .attr("d",d3.svg.arc() .innerRadius(distanceScale2(400)) .outerRadius(distanceScale2(520)) .startAngle((90 - d.key) * (Math.PI/180)) .endAngle(((90 - d.key) - 1) * (Math.PI/180)) ) .attr("transform", "translate(" + width/2 + "," + height + ")") .style("fill",horShadeScale(d.value)) .style("opacity",0); }) svg.selectAll(".elev-lines") .data(elevArray) .enter().append("line") .attr("class", function(d) { if (d==0) { return "elev-lines none";} else { return "elev-lines minor"; } }) .attr("x1",0) .attr("y1",height*.75) .attr("x2", function(d) { return distanceScale(400) * Math.cos((d)*Math.PI/180); }) .attr("y2", function(d) { return height*.75 - distanceScale(400) * Math.sin((d)*Math.PI/180); }) .style("opacity",0); svg.selectAll(".elev-label") .data(elevArray) .enter().append("text") .attr("class","elev-label") .attr("dy",".17em") .attr("x", function(d) { return distanceScale(400) * Math.cos((d)*Math.PI/180) + 5; }) .attr("y", function(d) { return height*.75 - distanceScale(400) * Math.sin((d)*Math.PI/180); }) .text(function(d) { return d + "°"; }) .style("opacity",0); svg.selectAll(".foul-lines") .data(horAngleArray) .enter().append("line") .attr("class", function(d) { if (d==0 || d==90) { return "foul-lines major";} else { return "foul-lines minor"; } }) .attr("x1",width/2) .attr("y1",height) .attr("x2", function(d) { return width/2 + distanceScale2(550 * Math.sin((d-45)*Math.PI/180)); }) .attr("y2", function(d) { return height - distanceScale2(550 * Math.cos((d-45)*Math.PI/180)); }) .style("opacity",0); distanceArcs.forEach(function(d) { svg.append("path") .attr("class","dist-arc") .attr("d",d3.svg.arc() .innerRadius(distanceScale2(d)) .outerRadius(distanceScale2(d+1)) .startAngle(-50 * (Math.PI/180)) .endAngle(50 * (Math.PI/180)) ) .attr("transform", "translate(" + width/2 + "," + height + ")") .style("fill","grey") .style("opacity",0); svg.append("text") .attr("class","dist-arc-text") .attr("x",width/2 + distanceScale2(d) * Math.sin(50*Math.PI/180) + 5) .attr("y",height - distanceScale2(d) * Math.cos(50*Math.PI/180)) .attr("dy",".5em") .text(function() { if (d == distanceArcs[0]) {return d + " feet";} else { return d; } }) .style("opacity",0) }) data = hitter.filterFunction(function(d) { return d == "Stanton, Giancarlo" || d == "Tulowitzki, Troy" || d == "Bautista, Jose" || d == "Donaldson, Josh" || d == "Jones, Adam" || d == "Dozier, Brian" || d == "Cespedes, Yoenis" || d == "Puig, Yasiel" || d == "Frazier, Todd" || d == "Morneau, Justin"; }).top(10000); svg.selectAll(".hr-dot") .data(data) .enter().append("circle") .attr("class", "hr-dot") .attr("id",function(d) { return "hr-" + d.id; }) .attr("r", 4) .attr("cx",distanceScale(0)) .attr("cy", height*.75) .style("opacity",0); } function showSpeed(data,transitionTime) { STAGE = 1; clearAll(transitionTime); collapseField(); showCaptions(1,true,PLAYER); data.forEach(function(hr) { svg.select("#hr-" + hr.id) .transition() .attr("cx", function(d) { return speedScale(d.speed) }) .attr("cy", function(d) { return height*.75 - distanceScale(d.apex)/5; }) .style("opacity",.2) .duration(transitionTime); }) longestCross.filter(null) data = hitter.filterExact(null).top(50000) speedDist.forEach(function(a) { svg.select("#speed-" + a.key) .transition() .attr("height",function(d) { return 100 *(d.value/speedMaxCount); }) .attr("y",function(d) { return (height*.75 - 50 - 100 *(d.value/speedMaxCount)); }) .duration(transitionTime) }) elOpacity("#speed-axis",transitionTime,1); } function showElevAngle(data,transitionTime) { STAGE = 2; collapseField(); clearAll(transitionTime); showCaptions(2,true,PLAYER); data.forEach(function(hr) { svg.select("#hr-" + hr.id) .transition() .attr("cx", function(d) { return speedScale(d.speed) }) .attr("cy", function(d) { return height*.75 - speedScale(d.speed) * Math.tan((d.elev_angle)*Math.PI/180); }) .style("opacity",.5) .duration(transitionTime); }) longestCross.filter(null) data = hitter.filterExact(null).top(50000) elOpacity(".elev-arc",transitionTime,.4); elOpacity(".elev-lines",transitionTime,1); elOpacity(".elev-label",transitionTime,1); } function showApex(data,transitionTime) { STAGE = 3; collapseField(); clearAll(transitionTime); showCaptions(3,true,PLAYER); data.forEach(function(hr) { svg.select("#hr-" + hr.id) .transition() .attr("cx", function(d) { return distanceScale(370 + ((d.distance - 300)/200) * 20); }) .attr("cy", function(d) { return height*.75 - apexScale(d.apex); }) .style("opacity",.2) .duration(transitionTime); }) longestCross.filter(null) data = hitter.filterExact(null).top(50000) apexDist.forEach(function(a) { svg.select("#apex-" + a.key) .transition() .attr("width",function(d) { return 100 *(d.value/apexMaxCount); }) .attr("x",function(d) { return distanceScale(360) - 100 *(d.value/apexMaxCount); }) .duration(transitionTime) }) elOpacity("#apex-axis",transitionTime,1); } function showDistance(data,transitionTime) { STAGE = 4; expandField(); clearAll(transitionTime); showCaptions(4,true,PLAYER); data.forEach(function(hr) { svg.select("#hr-" + hr.id) .transition() .attr("cx", function(d) { return distanceScale(d.distance); }) .attr("cy", function(d) { return height*.75 - (d.horiz_angle - 45)/4 - 10; }) .style("opacity",.2) .duration(transitionTime); }) longestCross.filter(null) data = hitter.filterExact(null).top(50000) distanceDist.forEach(function(a) { svg.select("#distance-" + a.key) .transition() .attr("height",function(d) { return 100 * (d.value/distanceMaxCount); }) .attr("y",function(d) { return (height*.75 - 50 - 100*(d.value/distanceMaxCount)); }) .duration(transitionTime) }) elOpacity("#distance-axis",transitionTime,1); } function showHorAngle(data,transitionTime) { STAGE = 5; fieldSize(-45,45,0,0,0,width,height,120,400,distanceScale2) clearAll(transitionTime); showCaptions(5,true,PLAYER); data.forEach(function(hr) { svg.select("#hr-" + hr.id) .transition() .attr("cx", function(d) { return width/2 + distanceScale2(d.distance * Math.sin((90 - d.horiz_angle)*Math.PI/180)); }) .attr("cy", function(d) { return height - distanceScale2(d.distance * Math.cos((90 - d.horiz_angle)*Math.PI/180)); }) .style("opacity",.5) .duration(transitionTime); }) longestCross.filter(null) data = hitter.filterExact(null).top(50000) elOpacity(".dist-arc-text",transitionTime,.4); elOpacity(".dist-arc",transitionTime,.4); elOpacity(".hor-arc",transitionTime,.4); elOpacity(".foul-lines",transitionTime,1) } function clearAll(transitionTime) { elOpacity(".start-dot",transitionTime/10,0); elOpacity(".start-text",transitionTime/10,0); elOpacity("#speed-axis",transitionTime,0); elOpacity(".foul-lines",transitionTime,0); elOpacity(".elev-lines",transitionTime,0); elOpacity("#apex-axis",transitionTime,0); elOpacity("#distance-axis",transitionTime,0); elOpacity(".elev-label",transitionTime,0); elOpacity(".elev-arc",transitionTime,0); elOpacity(".hor-arc",transitionTime,0); elOpacity(".dist-arc",transitionTime,0); elOpacity(".dist-arc-text",transitionTime,0); svg.selectAll(".dist-bars") .transition() .attr("height",0) .attr("y",height *.75 - 50) .duration(transitionTime) svg.selectAll(".apex-bars") .transition() .attr("x",distanceScale(360)) .attr("x",distanceScale(360)) .attr("width",0) .duration(transitionTime) svg.selectAll(".speed-bars") .transition() .attr("height",0) .attr("y",height*.75 - 50) .duration(transitionTime) d3.selectAll(".caption").remove(); d3.selectAll(".legend-bar-text").remove(); d3.selectAll(".legend-circle-text").remove(); d3.selectAll(".legend-bars").remove(); d3.selectAll(".legend-bars-text").remove(); } function elOpacity(el,duration,opacity) { d3.selectAll(el) .transition() .style("opacity",opacity) .duration(duration); } function fieldSize(angle1,angle2,strokeWidth,delay1,delay2,w,h,infield,outfield,scale) { d3.select(".infield") .transition() .delay(delay1) .attr("transform", "translate(" + w/2 + "," + h + ")") .attr("d",d3.svg.arc() .innerRadius(scale(0)) .outerRadius(scale(infield)) .startAngle((angle1) * (Math.PI/180)) .endAngle((angle2) * (Math.PI/180)) ) .duration(1000) d3.select(".outfield") .transition() .delay(delay1) .attr("transform", "translate(" + w/2 + "," + h + ")") .attr("d",d3.svg.arc() .innerRadius(scale(infield)) .outerRadius(scale(outfield)) .startAngle((angle1) * (Math.PI/180)) .endAngle((angle2) * (Math.PI/180)) ) .duration(1000); d3.select(".infield-line") .transition() .delay(delay2) .style("stroke-width",strokeWidth) .duration(1000); d3.select(".outfield-line") .transition() .delay(delay2) .style("stroke-width",strokeWidth) .duration(1000); } function collapseField() { fieldSize(90,90,2,0,600,0,height*.75,120,400,distanceScale); } function expandField() { fieldSize(45,135,0,0,0,0,height*.75,120,400,distanceScale); } function showCaptions(STAGE,longest,text) { if (longest == true) { if (STAGE == 1) { svg.append('foreignObject') .attr("class","caption") .attr("x",width/2) .attr("y",10) .attr("width",250) .attr("height",300) .append("xhtml:body") .html(stage1Caption); addDistLegend(speedScale(90),height*.75 - 170,speedScale(125),height*.75 - 20,text) } else if (STAGE == 2) { svg.append('foreignObject') .attr("class","caption") .attr("x",0) .attr("y",20) .attr("width",250) .attr("height",300) .append("xhtml:body") .html(stage2Caption); addGradientLegend(distanceScale(350),30,width/2-30,height*.75 - (fullWidth/12),elevLabelRange,3,2,text) } else if (STAGE == 3) { svg.append('foreignObject') .attr("class","caption") .attr("x",0) .attr("y",30) .attr("width",250) .attr("height",300) .append("xhtml:body") .html(stage3Caption); addDistLegend(distanceScale(360) - 150,height*.75 - apexScale(150),distanceScale(375),height*.75 - apexScale(180),text,"end") } else if (STAGE == 4) { svg.append('foreignObject') .attr("class","caption") .attr("x",function() { if (width > 750) { console.log('here'); return width/2 - 125; } else { return 0; } }) .attr("y",95) .attr("width",250) .attr("height",300) .append("xhtml:body") .html(stage4Caption); addDistLegend(distanceScale(400),height*.75 - 160,distanceScale(370),height*.75 + 40,text) } else if (STAGE == 5) { svg.append('foreignObject') .attr("class","caption") .attr("x",width/2 - 125) .attr("y",175) .attr("width",250) .attr("height",300) .append("xhtml:body") .html(stage5Caption); addGradientLegend(width/2 + 65,height - 40,width/2 + 100,0,horLabelRange,1,5,text) } } } function addDistLegend(barX,barY,circleX,circleY,text,textAnchor) { svg.append("text") .attr("class","legend-bar-text") .attr("x",barX) .attr("y",barY) .text("Overall HR distribution") svg.append("text") .attr("class","legend-circle-text") .style("text-anchor",textAnchor) .attr("x",circleX) .attr("y",circleY) .text(text) } function addGradientLegend(barX,barY,circleX,circleY,labelRange,ignore,back,text) { svg.append("text") .attr("class","legend-circle-text") .attr("x",circleX) .attr("y",circleY) .text(text) svg.selectAll(".legend-bars") .data(colorbrewer.Blues[9]) .enter().append("rect") .attr("class","legend-bars") .attr("x", function (d,i) { return barX + (i*20); }) .attr("y",barY) .attr("height",20) .attr("width",20) .style("fill", function(d) { return d; }); svg.selectAll(".legend-bars-text") .data(labelRange) .enter().append("text") .attr("class","legend-bars-text") .attr("x", function (d,i) { return barX + (i*20) - back; }) .attr("y",barY - 10) .attr("dy", ".35em") .text(function(d,i) { if ( i == 8) { return d + "% of all HRs" } else if ( i%2 != ignore) { return d; } }); } function changePlayer(data) { d3.selectAll(".hr-dot").remove() svg.selectAll(".hr-dot") .data(data) .enter().append("circle") .attr("class", "hr-dot") .attr("id",function(d) { return "hr-" + d.id; }) .attr("r", 4) .attr("cx",distanceScale(0)) .attr("cy", height*.75) .style("opacity",0); } $("#start").click(function(){ STAGE = 1; $(".players").removeClass("hide") $(".description").addClass("hide") renderStage(STAGE,0); flipButtons(); $("#speed-btn").addClass("active") $("#speed-btn").click(function(){ STAGE = 1; if (PLAYER == "All participants' HRs") { t = 0 } else { t = 1000 } $(".btn").removeClass("active") $(this).addClass("active") renderStage(STAGE,t); }) $("#angle-btn").click(function(){ STAGE = 2; if (PLAYER == "All participants' HRs") { t = 0 } else { t = 1000 } $(".btn").removeClass("active") $(this).addClass("active") renderStage(STAGE,t); }) $("#height-btn").click(function(){ STAGE = 3; if (PLAYER == "All participants' HRs") { t = 0 } else { t = 1000 } $(".btn").removeClass("active") $(this).addClass("active") renderStage(STAGE,t); }) $("#distance-btn").click(function(){ STAGE = 4; if (PLAYER == "All participants' HRs") { t = 0 } else { t = 1000 } $(".btn").removeClass("active") $(this).addClass("active") renderStage(STAGE,t); }) $("#location-btn").click(function(){ STAGE = 5; if (PLAYER == "All participants' HRs") { t = 0 } else { t = 1000 } $(".btn").removeClass("active") $(this).addClass("active") renderStage(STAGE,t); }) $("#next-btn").click(function(){ var temp = STAGE + 1; STAGE = Math.max(Math.min(temp,5),1) $(".btn").removeClass("active") if (STAGE == 1) { $("#speed-btn").addClass("active") } if (STAGE == 2) { $("#angle-btn").addClass("active") } if (STAGE == 3) { $("#height-btn").addClass("active") } if (STAGE == 4) { $("#distance-btn").addClass("active") } if (STAGE == 5) { $("#location-btn").addClass("active") } if (PLAYER == "All participants' HRs") { t = 0 } else { t = 1000 } renderStage(STAGE,t); }) }) $(".player-selector").click(function(){ $(".player-selector").removeClass("player-active") $(this).addClass("player-active") var playerSelection = $(this).attr("id") if (playerSelection == "bautista") { fullName = "Bautista, Jose" } else if (playerSelection == "tulowitzki") { fullName = "Tulowitzki, Troy" } else if (playerSelection == "donaldson") { fullName = "Donaldson, Josh" } else if (playerSelection == "jones") { fullName = "Jones, Adam" } else if (playerSelection == "cespedes") { fullName = "Cespedes, Yoenis"} else if (playerSelection == "frazier") { fullName = "Frazier, Todd" } else if (playerSelection == "morneau") { fullName = "Morneau, Justin" } else if (playerSelection == "puig") { fullName = "Puig, Yasiel" } else if (playerSelection == "stanton") { fullName = "Stanton, Giancarlo" } else if (playerSelection == "dozier") { fullName = "Dozier, Brian" } else if (playerSelection == "longest") { fullName = null } else if (playerSelection == "all") { fullName = "all" } if (fullName == null) { PLAYER = "100 longest HRs" hitter.filter(null) data = longestCross.filterRange([1,100]).top(100); } else if (fullName == "all") { PLAYER = "All participants' HRs" longestCross.filter(null) data = hitter.filterFunction(function(d) { return d == "Stanton, Giancarlo" || d == "Tulowitzki, Troy" || d == "Bautista, Jose" || d == "Donaldson, Josh" || d == "Jones, Adam" || d == "Dozier, Brian" || d == "Cespedes, Yoenis" || d == "Puig, Yasiel" || d == "Frazier, Todd" || d == "Morneau, Justin"; }).top(10000); } else { var comma = fullName.indexOf(",") PLAYER = fullName.slice(comma + 2,20) + " " + fullName.slice(0,comma) + "'s HRs"; longestCross.filter(null) data = hitter.filterExact(fullName).top(1000); } changePlayer(data); renderStage(STAGE,0); }) </script>
{{ rawDataset.count }} rows returned