Skip to content

Instantly share code, notes, and snippets.

@valex
Created January 19, 2018 19:45
Show Gist options
  • Select an option

  • Save valex/3c5f757d544bfa47728d28705726b449 to your computer and use it in GitHub Desktop.

Select an option

Save valex/3c5f757d544bfa47728d28705726b449 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<meta charset='utf-8'>
<html>
<head>
<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 class="container-fluid">
<div class="row">
<div class="col-sm-6">
<div id="scatterplot-chart-module"></div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script>
<script type='text/javascript' src='script.js'></script>
</body>
</html>
id first last avglaunch avgexitvelo maxexit
471 Kris Allen 7.4340000 80.4390030 80.439
444 John Fiorenza 25.0205000 87.3486659 90.366
463 David Flores 16.3210769 90.6016922 96.425
466 Jack Hartman 15.5962500 88.9420840 95.863
460 Hunter Jones 22.8016154 87.4951536 98.331
446 Marcus Judd 11.6091667 86.5193342 92.204
453 Blake Marabell 25.7681250 87.5226240 90.733
448 Tanner May 16.5153636 89.4465450 95.712
454 Luis Medina 15.2379091 87.4140001 94.573
457 Matt Moclair 17.3580000 88.0609175 91.952
452 Jordan Morrow 18.2746000 82.7912003 83.812
450 Austin Nickle 18.1268000 87.2209999 95.706
470 Ricky Presno 19.4675000 86.8034992 89.379
456 Christian Smallwood 14.0380769 91.2107691 96.225
445 Chris Tidwell 15.1037143 88.0677131 91.842
451 Yorvis Torrealba 15.8735714 87.1242872 93.810
447 Zach West 14.6356667 86.0375570 95.608
var SCATTERPLOT_CHART_APP = {
url: 'scatterplot.csv',
data: [],
options: {
chartModule: {
appendToSelector: '#scatterplot-chart-module',
width: 500,
height: 400,
margins: {top: 40,right: 10,bottom: 50,left: 60},
axisPadding: 0,
minX: 80,
maxX: 105,
minY: -10,
maxY: 50,
chartWidth: null,
chartHeight: null,
svg: null,
mainGroup: null,
scaleX: null,
scaleY: null,
}
},
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 {
id: +d["id"],
first_name: (''+d["first"]).trim(),
last_name: (''+d["last"]).trim(),
avglaunch: +d["avglaunch"],
avgexitvelo: +d["avgexitvelo"],
maxexit: +d["maxexit"]
}
});
that.initChart();
that.updateChart();
});
},
// ============================== CHART MODULE ==============================
initChart: function() {
var that = this;
var options = this.options.chartModule;
options.chartWidth = options.width - options.margins.left - options.margins.right,
options.chartHeight= options.height - options.margins.top - options.margins.bottom;
options.scaleX = d3.scaleLinear()
.domain([options.minX, options.maxX])
.range([0, options.chartWidth]);
options.scaleY = d3.scaleLinear()
.domain([options.minY, options.maxY])
.range([options.chartHeight, 0]);
options.svg = d3.select(options.appendToSelector)
.append("svg")
.attr("width", options.width)
.attr("height", options.height);
// top Label
var topLabel = options.svg.append('g')
.append('text')
.attr('font-size', '18')
.attr('font-weight', 'bold')
.text('Launch Angle vs. Exit Velocity');
// centering
var translate = {
x: options.margins.left + (options.chartWidth - topLabel.node().getBoundingClientRect().width) / 2,
y: 20
};
topLabel.attr('transform', 'translate('+translate.x+', '+translate.y+')');
// bottom Label
var bottomLabel = options.svg.append('g')
.append('text')
.attr('font-size', '16')
.attr('font-weight', 'bold')
.text('Exit Velocity (mph)');
// centering
translate = {
x: options.margins.left + (options.chartWidth - bottomLabel.node().getBoundingClientRect().width) / 2,
y: options.height - 5
};
bottomLabel.attr('transform', 'translate('+translate.x+', '+translate.y+')');
// left Label
var leftLabel = options.svg.append('g')
.append('text')
.attr('font-size', '16')
.attr('font-weight', 'bold')
.text('Launch Angle (deg)');
// centering
translate = {
x: 20,
y: options.height - ((options.height - leftLabel.node().getBoundingClientRect().width) / 2)
};
leftLabel.attr('transform', 'translate('+translate.x+', '+translate.y+') rotate(-90,0,0)');
},
updateChart: function(){
var that = this;
var options = this.options.chartModule;
// Y grid
var yGridlinesAxis = d3.axisLeft(options.scaleY);
var yGridlineNodes = options.svg.append('g')
.attr('transform', 'translate(' + (options.margins.left + options.chartWidth) + ',' + options.margins.top + ')')
.call(yGridlinesAxis.tickSize(options.chartWidth + options.axisPadding, 0, 0).tickFormat(""));
this.styleGridlineNodes(yGridlineNodes);
// X grid
var xGridlinesAxis = d3.axisBottom(options.scaleX);
var xGridlineNodes = options.svg.append('g')
.attr('transform', 'translate(' + options.margins.left + ',' + (options.height - options.margins.bottom + options.axisPadding) + ')')
.call(xGridlinesAxis.tickSize(-options.chartHeight - options.axisPadding, 0, 0).tickFormat(""));
this.styleGridlineNodes(xGridlineNodes);
// Axes
var xAxis = d3.axisBottom(options.scaleX);
var yAxis = d3.axisLeft(options.scaleY);
var yAxisNodes = options.svg.append('g')
.attr('transform', 'translate(' + (options.margins.left - options.axisPadding) + ',' + options.margins.top + ')')
.call(yAxis);
var xAxisNodes = options.svg.append('g')
.attr('transform', 'translate(' + options.margins.left + ',' + (options.height - options.margins.bottom + options.axisPadding) + ')')
.call(xAxis);
// add the tooltip area to the webpage
var tooltip = d3.select("body").append("div")
.attr("class", "sc-tooltip")
.style("opacity", 0);
options.mainGroup = options.svg.append('g')
.attr('transform', 'translate(' + options.margins.left + ',' + options.margins.top + ')');
options.mainGroup.selectAll('circle')
.data(this.data)
.enter()
.append('circle')
.attr('cx', function (d) { return options.scaleX(d.avgexitvelo); })
.attr('cy', function (d) { return options.scaleY(d.avglaunch); })
.attr('r', 4)
.attr('fill', 'steelblue')
.attr('stroke', 'steelblue')
.on("mouseover", function(d) {
tooltip.transition()
.duration(200)
.style("opacity", .9);
tooltip.html(d.first_name+' '+d.last_name+' (Max Exit: <b>'+d.maxexit.toFixed(1)+'</b>)')
.style("left", (d3.event.pageX + 5) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
},
styleGridlineNodes: function (axisNodes) {
axisNodes.selectAll('.domain')
.attr('fill', 'none')
.attr('stroke', 'none');
axisNodes.selectAll('.tick line')
.attr('fill', 'none')
.attr('stroke-width', 1)
.attr('stroke', 'lightgray');
}
};
SCATTERPLOT_CHART_APP.start();
div.sc-tooltip {
position: absolute;
text-align: center;
display: inline-block;
height: 28px;
line-height: 28px;
padding: 6px 10px 2px 10px;
font: 12px sans-serif;
background: black;
border: 0px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
pointer-events: none;
color:white;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment