Created
December 12, 2017 16:02
-
-
Save valex/203ee926e1bf8cc8db99575e610ffd44 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
playID | personID | pitchType | pitchSpeed (mph) | x Axis (ft) | y Axis (ft) | exit Speed (mph) | V Launch Angle (degrees) | H Launch Angle | Distance (ft) | |
---|---|---|---|---|---|---|---|---|---|---|
1 | 33 | FB | 88.657 | -2.012 | 2.009 | 77.567 | 25.678 | 0.008 | 209.09 | |
2 | 35 | CB | 66.786 | 0.015 | 1.909 | 85.678 | -7.134 | 20.654 | 40.678 | |
3 | 39 | FB | 87.614 | -0.567 | 4.554 | 65.678 | 0.004 | -10.567 | 70.012 | |
4 | 41 | FB | 87.909 | 0.991 | 1.45 | 100.032 | 11.098 | -25.789 | 380.09 | |
5 | 48 | CB | 68.982 | 3.09 | 0.91 | 83.56 | -2.569 | 17.908 | 300.092 | |
6 | 51 | FB | 93.338 | 1.553 | 3.008 | 88.55 | 35.983 | 2.345 | 320.098 | |
7 | 55 | CB | 80.009 | -0.897 | 2.009 | 78.654 | 40.093 | -7.654 | 250.98 | |
8 | 59 | FB | 92.432 | -0.009 | 2.567 | 103.456 | -9.906 | 4.345 | 50.45 | |
9 | 61 | FB | 93.556 | -0.023 | 3.002 | 95.674 | 2.567 | 11.45 | 108.456 | |
10 | 67 | CB | 79.098 | 3.976 | 4.89 | 91.89 | 11.345 | -40.09 | 290.12 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset='utf-8'> | |
<html> | |
<head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.0.0-beta/css/bootstrap.min.css" rel="stylesheet"> | |
<link rel='stylesheet' href='style.css'> | |
</head> | |
<body> | |
<div id="page-container" class="row justify-content-center"> | |
<div class="col-sm-4" id="distance-module"></div> | |
<div class="col-sm-4" id="exit-launch-angle-module"></div> | |
<div class="col-sm-4" id="exit-direction-module"></div> | |
</div> | |
<div class="row justify-content-center"> | |
<div class="col-sm-4" id="table-module"></div> | |
</div> | |
<script type='text/javascript' src='script.js'></script> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var BASEBALL_ANIM_APP = { | |
url: 'data.csv', | |
data: [], | |
activeIndex: 0, | |
timer: null, | |
animation: { | |
duration: 1000, | |
delay: 4000 | |
}, | |
tableModuleOptions:{ | |
id: 'baseball-app-table', | |
appendToSelector: '#table-module', | |
rowActiveClass:"active", | |
}, | |
distanceModuleOptions: { | |
id: 'distance', | |
appendToSelector: '#distance-module', | |
margins: {top: 10, right: 10, bottom: 10, left: 10}, | |
width: 300, | |
height: 300, | |
defaultBallColor:'#c6c6c6', | |
ballActiveClass:"active", | |
ballHoverClass:"hovered", | |
radii: [350, 250, 150], | |
mainGroup: null, | |
schemeRadius: 0, | |
schemeBasePoint: {x:0, y:0}, | |
}, | |
exitLaunchAngleModuleOptions: { | |
id: 'exit-angle', | |
appendToSelector: '#exit-launch-angle-module', | |
margins: {top: 10, right: 10, bottom: 10, left: 10}, | |
width: 300, | |
height: 200, | |
mainGroup: null, | |
schemeRadius: 0, | |
vectorLength: 0, | |
vectorArcGenerator: null, | |
schemeBasePoint: {x:0, y:0}, | |
}, | |
exitDirectionModuleOptions: { | |
id: 'exit-dir', | |
appendToSelector: '#exit-direction-module', | |
margins: {top: 10, right: 10, bottom: 10, left: 10}, | |
width: 300, | |
height: 200, | |
mainGroup: null, | |
schemeRadius: 0, | |
schemeBasePoint: {x:0, y:0}, | |
vectorArcGenerator: null, | |
}, | |
mainColor: '#005d80', | |
mainLightColor: '#3bafda', | |
start: function(){ | |
this.loadData(); | |
}, | |
loadData: function(){ | |
var that = this; | |
d3.csv(this.url, function (error, rawData) { | |
if (error) throw error; | |
that.data = rawData.map(function (d) { | |
return { | |
X: +d["x Axis (ft)"], | |
Y: +d["y Axis (ft)"], | |
exitSpeed: +d["exit Speed (mph)"], | |
vAngle: +d["V Launch Angle (degrees)"], | |
hAngle: +d["H Launch Angle"], | |
distance: +d["Distance (ft)"] | |
} | |
}); | |
that.initTableModule(); | |
that.initDistanceModule(); | |
that.initExitLaunchAngleModule(); | |
that.initExitDirectionModule(); | |
that.startTimer(); | |
}); | |
}, | |
initTableModule: function() { | |
var options = this.tableModuleOptions; | |
var columns = [ | |
{ | |
key: 'exitSpeed', | |
label: 'Exit velocity' | |
}, | |
{ | |
key: 'vAngle', | |
label: 'Vertical Launch' | |
}, | |
{ | |
key: 'hAngle', | |
label: 'Horiztonal Launch' | |
}, | |
{ | |
key: 'distance', | |
label: 'Distance' | |
}, | |
]; | |
var table = d3.select(options.appendToSelector).append('table') | |
.attr('id', options.id) | |
.attr('class', 'table'); | |
var thead = table.append('thead'); | |
var tbody = table.append('tbody'); | |
// append the header row | |
thead.append('tr') | |
.selectAll('th') | |
.data(columns) | |
.enter() | |
.append('th') | |
.text(function (column) { return column.label; }); | |
// create a row for each object in the data | |
var rows = tbody.selectAll('tr') | |
.data(this.data) | |
.enter() | |
.append('tr') | |
.attr('id', function(d,i){ return 'ball-'+i;}); | |
// create a cell in each row for each column | |
var cells = rows.selectAll('td') | |
.data(function (row) { | |
return columns.map(function (column) { | |
return {value: row[column.key]}; | |
}); | |
}) | |
.enter() | |
.append('td') | |
.text(function (d) { return d.value; }); | |
return table; | |
}, | |
initDistanceModule: function(){ | |
var that = this; | |
var options = this.distanceModuleOptions; | |
var graphWidth = options.width - options.margins.left - options.margins.right, | |
graphHeight = options.height - options.margins.top - options.margins.bottom; | |
var svg = d3.select(options.appendToSelector) | |
.append("svg") | |
.attr("width", options.width) | |
.attr("height", options.height); | |
options.mainGroup = svg.append('g') | |
.attr('transform', 'translate(' + options.margins.left + ',' + options.margins.top + ')') | |
.attr('id', options.id); | |
// title text | |
options.mainGroup.append("text") | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("font-weight", "bold") | |
.attr("font-size", "14px") | |
.attr("alignment-baseline", "hanging") | |
.attr("dominant-baseline", "hanging") // for firefox | |
.attr("class", "title") | |
.style("fill", this.mainColor) | |
.text("DISTANCE"); | |
// ft label | |
options.mainGroup.append("text") | |
.attr("x", graphWidth) | |
.attr("y", 28) | |
.attr("font-size", "18px") | |
.attr("alignment-baseline", "baseline") | |
.attr("dominant-baseline", "baseline") // for firefox | |
.attr("text-anchor", "end") | |
.style("fill", this.mainColor) | |
.html("ft"); | |
// ft value | |
options.mainGroup.append("text") | |
.attr("id", "ft-value") | |
.attr("x", graphWidth - 14) | |
.attr("y", 28) | |
.attr("font-weight", "bold") | |
.attr("font-size", "28px") | |
.attr("alignment-baseline", "baseline") | |
.attr("dominant-baseline", "baseline") // for firefox | |
.attr("text-anchor", "end") | |
.style("fill", this.mainColor) | |
.html("0"); | |
options.schemeRadius = Math.round(0.5 * graphWidth / Math.cos(45 * Math.PI / 180)); | |
options.schemeBasePoint = { | |
x: Math.round(0.5 * graphWidth), | |
y: graphHeight | |
}; | |
var arcGen = d3.arc() | |
.startAngle(-45 * Math.PI / 180) | |
.endAngle(45 * Math.PI / 180); | |
var radii = options.radii; | |
var innerRadius, outerRadius, iRadius; | |
for(var i=0; i < radii.length; i++){ | |
iRadius = radii[i] / d3.max(radii) * options.schemeRadius; | |
innerRadius = iRadius; | |
outerRadius = innerRadius; | |
if(i == 0){ | |
innerRadius = 0; | |
} | |
options.mainGroup.append('path') | |
.attr("d", arcGen({ | |
innerRadius: innerRadius, | |
outerRadius: outerRadius | |
})) | |
.attr("transform", 'translate('+options.schemeBasePoint.x+', '+options.schemeBasePoint.y+')') | |
.attr("fill", 'none') | |
.attr("stroke", '#777777') | |
.attr("stroke-width", '1'); | |
// labels left | |
options.mainGroup.append("text") | |
.attr("x", options.schemeBasePoint.x) | |
.attr("y", options.schemeBasePoint.y - iRadius) | |
.attr("transform", "translate(-3,0) rotate(-45,"+options.schemeBasePoint.x+", "+options.schemeBasePoint.y+")") | |
.attr("text-anchor", i == 0 ? "start" : "end") | |
.attr("font-size", "12px") | |
.attr("font-weight", "bold") | |
.attr("alignment-baseline", i == 0 ? "auto" : "middle") | |
.attr("dominant-baseline", i == 0 ? "auto" : "middle") // for firefox | |
.style("fill", '#777777') | |
.text(radii[i]); | |
// labels right | |
options.mainGroup.append("text") | |
.attr("x", options.schemeBasePoint.x) | |
.attr("y", options.schemeBasePoint.y - iRadius) | |
.attr("transform", "translate(3,0) rotate(45,"+options.schemeBasePoint.x+", "+options.schemeBasePoint.y+")") | |
.attr("text-anchor", i == 0 ? "end" : "start") | |
.attr("font-size", "12px") | |
.attr("font-weight", "bold") | |
.attr("alignment-baseline", i == 0 ? "auto" : "middle") | |
.attr("dominant-baseline", i == 0 ? "auto" : "middle") // for firefox | |
.style("fill", '#777777') | |
.text(radii[i]); | |
} | |
var scale = d3.scaleLinear() | |
.domain([0, d3.max(options.radii)]) | |
.range([0, options.schemeRadius]); | |
options.mainGroup.selectAll('circle') | |
.data(this.data) | |
.enter() | |
.append('circle') | |
.attr('id', function(d,i){return 'ball-'+i;}) | |
.attr('class', 'ball') | |
.attr('fill', options.defaultBallColor) | |
.attr('stroke', 'none') | |
.attr('r', 5) | |
.attr('cx', function(d, i){return options.schemeBasePoint.x + scale(d.distance * Math.sin(d.hAngle * Math.PI / 180))}) | |
.attr('cy', function(d, i){return options.schemeBasePoint.y - scale(d.distance * Math.cos(d.hAngle * Math.PI / 180))}) | |
.on('click', function(d, i) { | |
var el = d3.select(this); | |
that.setBallActive(i); | |
// update ft-value | |
options.mainGroup.select('#'+options.id+' #ft-value') | |
.text(Math.round(el.datum()['distance'])); | |
// stop Timer | |
that.stopTimer(); | |
that.setActiveIndex(i); | |
that.updateModules(); | |
}) | |
.on('mouseenter', function() { | |
var el = d3.select(this); | |
if(el.classed(options.ballActiveClass)) | |
return; | |
el.classed(options.ballHoverClass, true); | |
}) | |
.on('mouseout', function() { | |
var el = d3.select(this); | |
if(el.classed(options.ballActiveClass)) | |
return; | |
el.classed(options.ballHoverClass, false); | |
}); | |
}, | |
initExitLaunchAngleModule: function(){ | |
var options = this.exitLaunchAngleModuleOptions; | |
var graphWidth = options.width - options.margins.left - options.margins.right, | |
graphHeight = options.height - options.margins.top - options.margins.bottom; | |
var svg = d3.select(options.appendToSelector) | |
.append("svg") | |
.attr("width", options.width) | |
.attr("height", options.height); | |
options.mainGroup = svg.append('g') | |
.attr('transform', 'translate(' + options.margins.left + ',' + options.margins.top + ')') | |
.attr('id', options.id); | |
// title text | |
options.mainGroup.append("text") | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("font-weight", "bold") | |
.attr("font-size", "14px") | |
.attr("alignment-baseline", "hanging") | |
.attr("dominant-baseline", "hanging") // for firefox | |
.attr("class", "title") | |
.style("fill", this.mainColor) | |
.text("EXIT LAUNCH ANGLE"); | |
// angle text | |
options.mainGroup.append("text") | |
.attr("id", "angle-label") | |
.attr("x", graphWidth) | |
.attr("y", 0) | |
.attr("font-weight", "bold") | |
.attr("font-size", "28px") | |
.attr("alignment-baseline", "hanging") | |
.attr("dominant-baseline", "hanging") // for firefox | |
.attr("class", "angle") | |
.attr("text-anchor", "end") | |
.style("fill", this.mainColor) | |
.html("0°"); | |
options.schemeRadius = Math.round((graphHeight - 30) * 0.5); | |
options.vectorLength = Math.round(options.schemeRadius * 0.85); | |
options.schemeBasePoint = { | |
x: Math.round(1/3 * graphWidth), | |
y: graphHeight - options.schemeRadius | |
}; | |
// outer arc | |
var outerArc = d3.arc() | |
.innerRadius(0) | |
.outerRadius(0.6 * options.schemeRadius) | |
.startAngle(0) | |
.endAngle(180 * Math.PI / 180); | |
options.mainGroup.append('path') | |
.attr("d", outerArc) | |
.attr("transform", 'translate('+options.schemeBasePoint.x+', '+options.schemeBasePoint.y+')') | |
.attr("fill", '#dee0df') | |
.attr("stroke-width", '0'); | |
// inner arc | |
var innerArc = d3.arc() | |
.innerRadius(0) | |
.outerRadius(0.44 * options.schemeRadius) | |
.startAngle(0) | |
.endAngle(180 * Math.PI / 180); | |
options.mainGroup.append('path') | |
.attr("d", innerArc) | |
.attr("transform", 'translate('+options.schemeBasePoint.x+', '+options.schemeBasePoint.y+')') | |
.attr("fill", this.mainLightColor) | |
.attr("stroke", this.mainColor) | |
.attr("stroke-width", 0); | |
// vector arc | |
options.vectorArcGenerator = d3.arc() | |
.innerRadius(0) | |
.outerRadius(0.44 * options.schemeRadius) | |
.startAngle(90 * Math.PI / 180) | |
.endAngle(function(d) { return (90 - d) * Math.PI / 180; }); | |
options.mainGroup.append('path') | |
.attr("id", "vector-arc") | |
.attr("d", options.vectorArcGenerator(0)) | |
.attr("transform", 'translate('+options.schemeBasePoint.x+', '+options.schemeBasePoint.y+')') | |
.attr("fill", this.mainColor); | |
// vector | |
options.mainGroup.append("line") | |
.style("stroke", this.mainColor) | |
.attr("id", "vector") | |
.attr("x1", options.schemeBasePoint.x) | |
.attr("y1", options.schemeBasePoint.y) | |
.attr("x2", options.schemeBasePoint.x + options.vectorLength) | |
.attr("y2", options.schemeBasePoint.y) | |
.attr("stroke-width", 1.5); | |
// x axis | |
options.mainGroup.append("line") | |
.style("stroke", this.mainColor) // colour the line | |
.attr("x1", options.schemeBasePoint.x) // x position of the first end of the line | |
.attr("y1", options.schemeBasePoint.y) // y position of the first end of the line | |
.attr("x2", options.schemeBasePoint.x + options.schemeRadius) // x position of the second end of the line | |
.attr("y2", options.schemeBasePoint.y) | |
.attr("stroke-width", 3); | |
// y axis | |
options.mainGroup.append("line") | |
.style("stroke", this.mainColor) // colour the line | |
.attr("x1", options.schemeBasePoint.x) // x position of the first end of the line | |
.attr("y1", options.schemeBasePoint.y + options.schemeRadius) // y position of the first end of the line | |
.attr("x2", options.schemeBasePoint.x) // x position of the second end of the line | |
.attr("y2", options.schemeBasePoint.y - options.schemeRadius) | |
.attr("stroke-width", 3); | |
}, | |
initExitDirectionModule: function(){ | |
var options = this.exitDirectionModuleOptions; | |
var graphWidth = this.exitDirectionModuleOptions.width - this.exitDirectionModuleOptions.margins.left - this.exitDirectionModuleOptions.margins.right, | |
graphHeight = this.exitDirectionModuleOptions.height - this.exitDirectionModuleOptions.margins.top - this.exitDirectionModuleOptions.margins.bottom; | |
var svg = d3.select(options.appendToSelector) | |
.append("svg") | |
.attr("width", options.width) | |
.attr("height", options.height); | |
options.mainGroup = svg.append('g') | |
.attr('transform', 'translate(' + options.margins.left + ',' + options.margins.top + ')') | |
.attr('id', options.id); | |
// Add the Title | |
options.mainGroup.append("text") | |
.attr("x", 0) | |
.attr("y", 0) | |
.attr("font-weight", "bold") | |
.attr("font-size", "14px") | |
.attr("alignment-baseline", "hanging") | |
.attr("dominant-baseline", "hanging") // for firefox | |
.attr("class", "title") | |
.style("fill", this.mainColor) | |
.text("EXIT DIRECTION"); | |
options.mainGroup.append("text") | |
.attr("id", "angle-label") | |
.attr("x", graphWidth) | |
.attr("y", 0) | |
.attr("font-weight", "bold") | |
.attr("font-size", "28px") | |
.attr("alignment-baseline", "hanging") | |
.attr("dominant-baseline", "hanging") // for firefox | |
.attr("class", "angle") | |
.attr("text-anchor", "end") | |
.style("fill", this.mainColor) | |
.html("0°"); | |
options.schemeRadius = Math.round(graphWidth * 0.5 * 0.66); | |
options.schemeBasePoint = { | |
x: Math.round(graphWidth / 2), | |
y: graphHeight | |
}; | |
// outer arc | |
var outerArc = d3.arc() | |
.innerRadius(0) | |
.outerRadius(4/5 * options.schemeRadius) | |
.startAngle(-45 * Math.PI / 180) | |
.endAngle(45 * Math.PI / 180); | |
options.mainGroup.append('path') | |
.attr("d", outerArc) | |
.attr("transform", 'translate('+options.schemeBasePoint.x+', '+options.schemeBasePoint.y+')') | |
.attr("fill", '#dee0df') | |
.attr("stroke-width", '0'); | |
// inner arc | |
var innerArc = d3.arc() | |
.innerRadius(0) | |
.outerRadius(4/7 * options.schemeRadius) | |
.startAngle(-45 * Math.PI / 180) | |
.endAngle(45 * Math.PI / 180); | |
options.mainGroup.append('path') | |
.attr("d", innerArc) | |
.attr("transform", 'translate('+options.schemeBasePoint.x+', '+options.schemeBasePoint.y+')') | |
.attr("fill", this.mainLightColor) | |
.attr("stroke", this.mainColor) | |
.attr("stroke-width", 2); | |
// vector arc | |
options.vectorArcGenerator = d3.arc() | |
.innerRadius(0) | |
.outerRadius(4/7 * options.schemeRadius) | |
.startAngle(0) | |
.endAngle(function(d) { return d * Math.PI / 180; }); | |
options.mainGroup.append('path') | |
.attr("id", "vector-arc") | |
.attr("d", options.vectorArcGenerator(0)) | |
.attr("transform", 'translate('+options.schemeBasePoint.x+', '+options.schemeBasePoint.y+')') | |
.attr("fill", this.mainColor); | |
options.mainGroup.append("line") | |
.style("stroke", this.mainColor) // colour the line | |
.attr("x1", options.schemeBasePoint.x) // x position of the first end of the line | |
.attr("y1", options.schemeBasePoint.y) // y position of the first end of the line | |
.attr("x2", options.schemeBasePoint.x + options.schemeRadius) // x position of the second end of the line | |
.attr("y2", options.schemeBasePoint.y - options.schemeRadius) | |
.attr("stroke-width", 3); | |
options.mainGroup.append("line") | |
.style("stroke", this.mainColor) // colour the line | |
.attr("x1", options.schemeBasePoint.x) // x position of the first end of the line | |
.attr("y1", options.schemeBasePoint.y) // y position of the first end of the line | |
.attr("x2", options.schemeBasePoint.x - options.schemeRadius) // x position of the second end of the line | |
.attr("y2", options.schemeBasePoint.y - options.schemeRadius) | |
.attr("stroke-width", 3); | |
// vector | |
options.mainGroup.append("line") | |
.style("stroke", this.mainColor) // colour the line | |
.attr("id", "vector") // x position of the first end of the line | |
.attr("x1", options.schemeBasePoint.x) // x position of the first end of the line | |
.attr("y1", options.schemeBasePoint.y) // y position of the first end of the line | |
.attr("x2", options.schemeBasePoint.x) // x position of the second end of the line | |
.attr("y2", options.schemeBasePoint.y - options.schemeRadius) | |
.attr("stroke-width", 1.5); | |
}, | |
animateExitLaunchAngleModule: function(){ | |
var options = this.exitLaunchAngleModuleOptions; | |
var data = this.data[this.activeIndex]; | |
options.mainGroup | |
.select('#'+options.id+' #vector') | |
.datum(data) | |
.transition() | |
.duration(this.animation.duration) | |
.tween("animations", function(d){ | |
var el = d3.select(this); | |
var angleLabel = d3.select('#'+options.id+' #angle-label'); | |
var vectorArc = d3.select('#'+options.id+' #vector-arc'); | |
var X2 = +el.attr("x2"); | |
var Y2 = +el.attr("y2"); | |
var fromAngle = 180 / Math.PI * Math.asin((options.schemeBasePoint.y - Y2) / options.vectorLength); | |
var toAngle = d['vAngle']; | |
var iAngle = d3.interpolateNumber(fromAngle, toAngle); | |
return function(t){ | |
el.attr("x2", options.schemeBasePoint.x + (options.vectorLength * Math.cos(iAngle(t) * Math.PI / 180))); | |
el.attr("y2", options.schemeBasePoint.y - (options.vectorLength * Math.sin(iAngle(t) * Math.PI / 180))); | |
angleLabel.html(Math.round(iAngle(t)) + "°"); | |
vectorArc.attr("d", options.vectorArcGenerator(iAngle(t))) | |
} | |
}) | |
}, | |
animateExitDirectionModule: function(){ | |
var options = this.exitDirectionModuleOptions; | |
var data = this.data[this.activeIndex]; | |
options.mainGroup | |
.select('#'+options.id+' #vector') | |
.datum(data) | |
.transition() | |
.duration(this.animation.duration) | |
.tween("animations", function(d){ | |
var el = d3.select(this); | |
var angleLabel = d3.select('#'+options.id+' #angle-label'); | |
var vectorArc = d3.select('#'+options.id+' #vector-arc'); | |
var X2 = +el.attr("x2"); | |
var Y2 = +el.attr("y2"); | |
var fromAngle = 180 / Math.PI * Math.asin((X2 - options.schemeBasePoint.x) / options.schemeRadius); | |
var toAngle = d['hAngle']; | |
var iAngle = d3.interpolateNumber(fromAngle, toAngle); | |
return function(t){ | |
el.attr("x2", options.schemeBasePoint.x + (options.schemeRadius * Math.sin(iAngle(t) * Math.PI / 180))); | |
el.attr("y2", options.schemeBasePoint.y - (options.schemeRadius * Math.cos(iAngle(t) * Math.PI / 180))); | |
var suffix = "°"; | |
if(iAngle(t) >= 0){ | |
suffix += 'R'; | |
}else{ | |
suffix += 'L'; | |
} | |
angleLabel.html(Math.round(iAngle(t)) + suffix); | |
vectorArc.attr("d", options.vectorArcGenerator(iAngle(t))) | |
} | |
}) | |
}, | |
animateDistanceModule: function(){ | |
var options = this.distanceModuleOptions; | |
var data = this.data[this.activeIndex]; | |
this.setBallActive(this.activeIndex); | |
// update ft-value | |
options.mainGroup.select('#'+options.id+' #ft-value') | |
.text(Math.round(data['distance'])); | |
}, | |
animateTableModule: function(){ | |
this.setRowActive(this.activeIndex); | |
}, | |
startTimer: function(){ | |
var that = this; | |
var animationDelay = this.animation.duration + this.animation.delay; | |
var dataLength = this.dataLength(); | |
var prevTickNum = null; | |
var tickNum; | |
this.timer = d3.timer(function(elapsed){ | |
tickNum = Math.floor(elapsed / animationDelay); | |
if(prevTickNum !== tickNum){ | |
prevTickNum = tickNum; | |
that.setActiveIndex(tickNum % dataLength); | |
that.updateModules(); | |
} | |
}) | |
}, | |
stopTimer: function(){ | |
this.timer.stop(); | |
}, | |
updateModules: function(){ | |
this.animateExitLaunchAngleModule(); | |
this.animateExitDirectionModule(); | |
this.animateDistanceModule(); | |
this.animateTableModule(); | |
}, | |
setActiveIndex:function(index){ | |
this.activeIndex = index; | |
}, | |
setRowActive: function(index){ | |
var options = this.tableModuleOptions; | |
var table = d3.select('#'+options.id); | |
var tr = table.select('#ball-'+index); | |
// only one active | |
var alreadyIsActive = tr.classed(options.rowActiveClass); | |
if(alreadyIsActive) | |
return; | |
table.selectAll('#'+options.id+' tr') | |
.classed(options.rowActiveClass, false); | |
tr.classed(options.rowActiveClass, !alreadyIsActive); | |
}, | |
setBallActive:function(index){ | |
var options = this.distanceModuleOptions; | |
var el = d3.select('#'+options.id+' #ball-'+index); | |
// only one active | |
var alreadyIsActive = el.classed(options.ballActiveClass); | |
if(alreadyIsActive) | |
return; | |
options.mainGroup.selectAll('#'+options.id+' .ball') | |
.classed(options.ballActiveClass, false); | |
el.classed(options.ballActiveClass, !alreadyIsActive); | |
el.classed(options.ballHoverClass, false); | |
}, | |
isDataLoaded: function(){ | |
return this.dataLength(); | |
}, | |
dataLength: function(){ | |
return this.data.length; | |
} | |
}; | |
BASEBALL_ANIM_APP.start(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
circle.ball.active{ | |
fill: #005d80; | |
} | |
circle.ball.hovered{ | |
fill: #3bafda; | |
} | |
table { | |
border-collapse: collapse; | |
} | |
.table { | |
width: 100%; | |
max-width: 100%; | |
margin-bottom: 1rem; | |
background-color: transparent; | |
font-size: 0.92rem; | |
} | |
.table thead th { | |
vertical-align: bottom; | |
border-bottom: 2px solid #e9ecef; | |
} | |
.table tr.active{ | |
background-color: #c5e8f5; | |
} | |
.table td, .table th { | |
padding: .3rem; | |
vertical-align: top; | |
border-top: 1px solid #e9ecef; | |
text-align: center; | |
} | |
.table td, .table th { | |
padding: .3rem; | |
vertical-align: top; | |
border-top: 1px solid #e9ecef; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment