xxxxxxxxxx
<meta charset="utf-8">
<title>Olympics 100 Meter Dash</title>
<style type="text/css">
body {
font-family: arial, sans;
font-size: 13px;
margin: 10px auto;
max-width:900px;
}
.g-graphic-container{
position: relative;
max-width: 900px;
}
svg{
max-width: 900px;
/* border: thin solid #f0f;*/
}
.line {
fill:none;
}
.axis text {
font-size: 12px;
fill: #777;
}
.axis path {
display: none;
}
.axis line {
stroke-width:.3px;
stroke: #dedede;
/*stroke-dasharray: 2px 2px;*/
}
.country-container {
display: inline-block;
margin-right:10px;
}
.info{
position: absolute;
top: 10px;
left: 250px;
}
.country-label{
position: absolute;
top:15px;
left:150px;
}
#countrySelect{
position: absolute;
top: 30px;
left:500px;
}
#decileSelect{
position: absolute;
top: 30px;
left:650px;
}
table {
width: 120px;
margin: 10px 10px;
border-collapse: collapse;
position: absolute;
}
.g-num {
text-align: left;
}
td {
padding: 3px 0;
border-bottom: 1px solid #dedede;
}
.medal-table{
position: absolute;
top: 100px;
left: 120px;
background-color: white;
}
.tooltip{
border: thin solid #dedede;
visibility: hidden;
display: inline-block;
position: absolute;
left:275px;
top:20px;
background-color: white;
padding: 10px;
}
.g-row{
cursor: pointer;
}
h1{
position: relative;
font-size: 25px;
top:10px;
left: 200px;
color:#606060;
}
path{
fill:white;
fill-opacity: 0.1;
stroke: #f0f;
}
path:hover{
fill:orange;
}
</style>
<body>
<div class="g-graphic-container">
<h1>Olympic 100 Meter Dash Records</h1>
<div class="info"></div>
<div class="tooltip">
<div class="athlete-name"></div>
<div class="origin-country"></div>
<div class="win-year"></div>
<div class="medal-status"></div>
<div class="meters-back"></div>
<div class="seconds-back"></div>
</div>
</div>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<script type="text/javascript">
var countryMap = {
"USA": "United States",
"GBR": "Great Britain",
"JAM": "Jamaica",
"CAN": "Canada",
"TRI": "Trinidad and Tobago",
"AUS": "Australia",
"GER": "Germany",
"NAM": "Namibia",
"CUB": "Cuba",
"URS": "Soviet Union",
"BAR": "Barbados",
"EUA": "United Team of Germany",
"HUN": "Hungary",
"PAN": "Panama",
"NED": "Netherlands",
"POR": "Portugal",
"NZL": "New Zealand",
"RSA": "South Africa",
"BUL": "Bulgaria"
};
var colors = {
"GOLD": "#efcf6d",
"SILVER": "#b0b0b1",
"BRONZE": "#c59e8a"
}
var margin = {top: 20, right: 50, bottom: 20, left: 80};
var reSpace = new RegExp(" ", 'g');
var graphic = d3.select(".g-graphic-container");
var width = graphic.node().clientWidth - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var xScale = d3.scale.linear()
.range([width,0]);
var yScale = d3.scale.ordinal()
// .range([height, 0]);
.rangeRoundPoints([0, height]);
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(-height)
.tickPadding(8)
.tickFormat(d3.round)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(yScale)
.tickSize(-width)
.tickPadding(8)
.orient("right");
var globalData;
//https://stackoverflow.com/questions/14167863/how-can-i-bring-a-circle-to-the-front-with-d3
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
var svg = d3.select("body").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 countryNest;
d3.tsv("medalists.tsv", ready);
function mouseoverMedal(d){
var sel = d3.select(this);
sel.moveToFront();
sel.style("stroke","black").style("stroke-width","2px");
d3.select(".tooltip")
.style("visibility","visible")
.style("transform","translate("+(d3.mouse(this)[0]-366)+"px,"+(d3.mouse(this)[1]-10)+"px)");
d3.select(".athlete-name").text(d.name);
d3.select(".win-year").text(d.year);
d3.select(".medal-status").text(d.medal);
d3.select(".meters-back").text("Meters Back: "+Number((d.metersBack).toFixed(4)));
d3.select(".seconds-back").text("Seconds Behind: "+Number((d.secondsBehind).toFixed(4)));
d3.select(".origin-country").text(d.country);
}
function mouseoverTable(d){
d3.select(this).style("background-color","#fdfd96");
d3.selectAll("#"+d.key.replace(reSpace,"-"))
.style("stroke","black")
.style("stroke-width","2px");
}
function mouseleaveMedal(){
d3.select(".tooltip").style("visibility","hidden");
d3.select(this).style("stroke","none");
}
function mouseleaveTable(d){
d3.select(this).style("background-color","white");
d3.selectAll("#"+d.key.replace(reSpace,"-"))
.style("stroke","none");
}
function createTable(countryNest){
var table = d3.select("body")
.append("table")
.attr("class","medal-table");
var row = table.selectAll(".g-row")
.data(countryNest)
.enter().append("tr")
.attr("class", "g-row")
.on("mouseover",mouseoverTable)
.on("mouseleave",mouseleaveTable);
row.append("td")
.attr("class", "g-x g-num")
.text(function(d) { return d.key;});
row.append("td")
.attr("class", "g-y g-num")
.text(function(d){ return d.values;});
}
function polygon(d) {
return "M" + d.join("L") + "Z";
}
//https://bl.ocks.org/mbostock/8033015
function addVoronoi(){
var voronoi = d3.geom.voronoi()
.clipExtent([[-margin.left, -margin.top], [width + margin.right, height + margin.bottom]]);
verticies = globalData.map(function(d){
//needs a random for some reason...
return [xScale(d.metersBack)+Math.random(),yScale(d.year)+Math.random()]
});
svg.append("g").selectAll("path")
.data(voronoi(verticies), polygon)
.enter().append("path")
.attr("d", polygon)
//bind the mouseover data to the global data datum by index, not the polygon itself
.datum(function(d,i){return globalData[i]})
.on("mouseover",function(d){
console.log(d);
});
}
function ready(error, data) {
if (error) return console.warn(error);
var winnerTime = parseFloat(data[0].time);
data.forEach(function(d){
d.time = parseFloat(d.time);
d.countryCode = d.countryCode.trim();
d.country = countryMap[d.countryCode];
d.medal =d.medal.trim();
//100M Dash
d.secondsBehind = d.time - winnerTime;
var metersPerSecond = 100/d.time;
d.metersBack = d.secondsBehind * metersPerSecond;
});
globalData = data;
var countryNest = d3.nest()
.key(function(d){return d.country;})
.rollup(function(leaves) { return leaves.length; })
.entries(data);
countryNest.sort(function(a,b){return b.values - a.values; });
var years = data.map(function(d){return d.year;})
yearArray = d3.set(years).values();
xScale.domain(d3.extent(data,function(d){return d.metersBack;}));
yScale.domain(yearArray.reverse());
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis)
.selectAll("g");
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" +width+ ",0)")
.call(yAxis);
addVoronoi();
svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("r",5)
.attr("class","medal")
.attr("id",function(d){return d.country.replace(reSpace,"-");})
.attr("cx",function(d){return xScale(d.metersBack);})
.attr("cy",function(d){return yScale(d.year)})
.style("fill",function(d){return colors[d.medal];})
.on("mouseover",mouseoverMedal)
.on("mouseleave", mouseleaveMedal);
createTable(countryNest);
}
function updateWindow(){
width = graphic.node().clientWidth - margin.left - margin.right;
if(width<=460){
d3.select(".medal-table").style("visibility","hidden").style("left","50px");
d3.select("h1").style("font-size","11px");
}
else{
d3.select("h1").style("font-size","25px");
d3.select(".medal-table").style("visibility","visible");
}
xScale.range([width,0]);
d3.select("svg").attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.selectAll("circle")
.attr("cx",function(d){return xScale(d.metersBack);});
svg.select(".y")
.attr("transform", "translate(" +width+ ",0)");
svg.select(".x")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis);
}
window.onresize = updateWindow;
</script>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js