xxxxxxxxxx
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="spinner.css">
<style type="text/css">
body {
background:#fff;
filter: sepia(.95);
-webkit-filter: sepia(.95);
}
h1 {
text-align:center;
font-family: monospace;
margin-top:50px;
text-transform: uppercase;
fill: #000;
font-size: 24px;
}
h2 {
text-align: center;
font-family: monospace;
font-size: 12px;
text-transform: uppercase;
font-weight: 200;
}
text.division, text.league {
font-family: monospace;
text-transform: uppercase;
font-size:15px;
fill:#000;
}
div.container {
width:960px;
margin:20px auto;
height:500px;
}
div.league {
margin-top:35px;
}
div.division {
display:inline-block;
margin-right:5px;
}
svg {
overflow: visible;
}
path.game-line{
fill:none;
stroke-width:1px;
stroke: #555;
}
path.game-line:hover{
stroke-width:2px;
}
path.game-line.positive {
stroke-width:2px;
}
path.game-line.positive:hover {
stroke-width:3px;
}
text.team-name {
font-family: sans-serif;
font-size:8px;
text-transform: uppercase;
fill: #333;
}
.axis text{
font-family: sans-serif;
font-size:11px;
text-transform: uppercase;
fill: #666;
font-weight: 200;
}
path.domain {
fill:none;
}
.tick line{
fill: none;
stroke: #999;
shape-rendering: crispEdges;
stroke-width: 1px;
opacity:.75;
}
.game-circle {
fill: #333;
stroke: #fff;
stroke-width:1px;
}
</style>
<body>
<h1>baseball: diagram showing "net" wins during the 2015 season</h1>
<h2>Inspired by <a href="https://tinyletter.com/abovechart/letters/the-chicago-daily-tribune-oct-10-1909" target="_blank">The Chicago Daily Tribune</a>, <a href="https://www.twitter.com/kevinQ" target="_blank">Kevin Quealy</a>, & <a href="https://bl.ocks.org/pstuffa" target="_blank">Paul Buffa</a>. Created by <a href="https://www.twitter.com/samirrayani" target="_blank">Samir Rayani</a></h2>
<div class="container">
<div id="cssload-pgloading">
<div class="cssload-loading"></div>
</div>
</div>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<script>
var divisionOrder = ["west", "central", "east"];
var format = d3.time.format("%Y-%m-%d");
var container = d3.select("div.container");
var margin = {top: 5, right: 50, bottom: 5, left: 5};
var width = container.node().getBoundingClientRect().width - margin.left - margin.right,
height = container.node().getBoundingClientRect().height - margin.top - margin.bottom;
var xScale = d3.time.scale()
.range([0, width/3 - margin.right - margin.left]);
var yScale = d3.scale.linear()
.range([height/2,0]);
var xAxis = d3.svg.axis()
.scale(xScale)
.innerTickSize(height/2)
.outerTickSize(0)
.tickFormat(d3.time.format("%b"))
.orient("top");
var x2Axis = d3.svg.axis()
.scale(xScale)
.orient("top")
.innerTickSize(height/2)
.outerTickSize(0)
.ticks(d3.time.days, 1)
.tickFormat("");
var yAxis = d3.svg.axis()
.scale(yScale)
.innerTickSize((width-margin.left-margin.right-20)/3)
.outerTickSize(0)
.ticks(12)
.orient("right");
drawChart = function(data) {
d3.select("#cssload-pgloading").remove();
var league = container.selectAll(".league")
.data(data, function(d) { return d.key; })
.enter()
.append("div")
.attr("class", "league" );
league.append("svg")
.attr("width", 15)
.attr("height", height/2)
.append("text")
.attr("class", "league")
.text(function(d){
return d.key == "AL" ? "American League" : "National League";
})
.attr("transform", "translate(0,50) rotate(-90)")
.style("text-anchor", "end");
var division = league.selectAll(".division")
.data(function(d) { return d.values; })
.enter()
.append("div")
.attr("class", "division")
.style("width", d3.round(width/3) + "px");
var divisionGroup = division.append("svg")
.attr("width", (width - margin.left - margin.right)/3)
.attr("height", (height + margin.top + margin.bottom)/2)
.append("g")
.attr("transform","translate(" + margin.left + "," + margin.top + ")");
divisionGroup.append("g")
.attr("class", "x axis minor")
.attr("transform","translate(0," + height/2 + ")")
.call(x2Axis);
divisionGroup.append("g")
.attr("class", "x axis")
.attr("transform","translate(0," + height/2 + ")")
.call(xAxis)
.selectAll("text")
.attr("y", 4)
.attr("x", -9)
.attr("transform", "rotate(-90)")
.style("text-anchor", "end");
divisionGroup.append("g")
.attr("class", "y axis")
.call(yAxis);
divisionGroup.append("text")
.text(function(d) { return d.key; })
.attr("class", "division")
.attr("transform", "translate(40,"+(height-margin.bottom-margin.top-47)/2+")");
var lineFn = d3.svg.line()
.x(function(d) { return xScale(d.formattedDate); })
.y(function(d) { return yScale(d.cumulative); });
var gameLine = divisionGroup.selectAll(".game-line")
.data(function(d){ return d.values; })
.enter()
.append("g");
gameLine.append("path")
.attr("d", function(d) {
return lineFn(d.values);
})
.attr("class", "game-line")
.classed("positive", function(d){ return d.positive; });
gameLine.selectAll(".game-circle")
.data(function(d) { return [d.values[d.values.length-1]]; })
.enter()
.append("circle")
.attr("class", "game-circle")
.attr("cx", function(d) { return xScale(d.formattedDate); })
.attr("cy", function(d) { return yScale(d.cumulative); })
.attr("r", function(d,i,c,k) { return (d.last) ? 3 : 0; });
gameLine.selectAll(".team-name")
.data(function(d) { return [d.values[d.values.length-1]]; })
.enter()
.append("text")
.attr("class", "team-name")
.text(function(d){ return d.team; })
.attr("transform", function(d){
var x = xScale(d.formattedDate)+5;
var y = yScale(d.cumulative)+3+d.nudge;
return "translate("+x+","+y+")";
});
};
clean = function(d) {
d.formattedDate = format.parse(d.date_str2);
d.pct = +d.pct;
d.win_loss = (d.result == "W") ? 1 : -1;
d.nudge = (d.team=="DET" || d.team=="TBR") ? -5 : 0;
d.nudge = (d.team=="BOS" || d.team=="NYY" || d.team=="CHW") ? 3 : d.nudge;
return d;
};
ready = function(err, data) {
var gameByLeagueByDivision = d3.nest()
.key(function(d) { return d.league; })
.key(function(d) { return d.division; })
.key(function(d) { return d.team; })
.entries(data);
gameByLeagueByDivision.forEach(function(league){
league.values.sort(function(a,b){
return divisionOrder.indexOf(a.key) - divisionOrder.indexOf(b.key);
});
league.values.forEach(function(division){
division.values.forEach(function(team){
var cumulative = 0;
team.values.forEach(function(game,i){
game.cumulative = cumulative + game.win_loss;
cumulative = game.cumulative;
game.last = (i==team.values.length-1);
});
team.positive = cumulative > 0;
});
});
});
xScale.domain(d3.extent(data, function(d){ return d.formattedDate; }));
yScale.domain(d3.extent(data, function(d){ return d.cumulative; }));
// yScale.domain([-50,50]);
drawChart(gameByLeagueByDivision);
};
// d3.tsv("lookup.tsv", clean, ready);
d3.csv("games.csv", clean, ready);
</script>
</body>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js