Created
January 25, 2017 03:44
-
-
Save chemok78/8d0e4894c426a4208e41a255967bb8c3 to your computer and use it in GitHub Desktop.
D3 JS Scatterplot Graph Fastest Times Ever Up Alpe d'Huez
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 url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json"; | |
d3.json(url, function (json) { | |
var data = json; | |
//set dimensions of SVG container and chart area | |
var margin = {top: 60, right: 120, bottom: 80, left: 80}; | |
//inner width for the chart, within SVG element | |
var w = 1000 - margin.left - margin.right; | |
//inner height for the chart, within SVG element | |
var h = 800 - margin.top - margin.bottom; | |
var xLeftMargin = 5; | |
//create SVG container and append to DOM | |
var svg = d3.select("#chart") | |
.append("svg") | |
.attr("width", w + margin.left + margin.right) | |
//width of SVG element is inner chart area + margins | |
.attr("height", h + margin.top + margin.bottom) | |
//height of SVG element is inner chart area + margins | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")") | |
//take the SVG selection | |
//append g element and move it to the 0,0 position for the chart | |
//all the chart elements will be appended to the this g element | |
var maxRank = d3.max(data, function(d){ | |
//get the highest number of ranking from data | |
return d.Place; | |
}); | |
var minSeconds = d3.min(data, function(d){ | |
return d.Seconds; | |
}); | |
var maxSeconds = d3.max(data, function(d){ | |
return d.Seconds; | |
}); | |
//color codes and label | |
var color = [ | |
{ | |
"code": "#FF7F0E", | |
"text": "No Doping allegations" | |
}, | |
{ | |
"code": "#1F77B4", | |
"text": "Doping allegations" | |
} | |
]; | |
//function to format seconds to minutes in X time scale | |
var formatTime = d3.timeFormat("%M:%S"); | |
var formatSeconds = formatMinutes = function(d) { return formatTime(new Date(2016, 0, 0, 0, 1, d));}; | |
//Create linear X Scale for time using seconds | |
var xScale = d3.scaleLinear() | |
.domain([maxSeconds + xLeftMargin, minSeconds - 30]) | |
//max seconds + margin, so the xScale does not start at maxSeconds | |
.range([0,w]); | |
var xAxis = d3.axisBottom() | |
.scale(xScale) | |
.tickSize(-h,0) | |
.ticks(10) | |
.tickFormat(formatMinutes) | |
var xLabel = svg.append("text") | |
.text("Time in Minutes") | |
.attr("x", w/2) | |
.attr("y", h + (margin.bottom/2)) | |
.attr("font-family", "roboto slab") | |
.attr("font-size", "14px") | |
//Create linear Y scale using ranking | |
var yScale = d3.scaleLinear() | |
.domain([0, maxRank + 2]) | |
//maxRank - margin, so the yScale does not start at maxRank | |
.range([0,h]); | |
var yAxis = d3.axisLeft() | |
.scale(yScale) | |
.ticks(10) | |
.tickSize(-w,0) | |
.tickValues([1,5,10,15,20,25,30,35]); | |
var yLabel = svg.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", 0 - (margin.left/2)) | |
.attr("x", 0 - (h/2)) | |
.style("text-anchor", "middle") | |
.attr("font-family", "roboto slab") | |
.attr("font-size", "14px") | |
.text("All time ranking") | |
.attr("class", "ylabel"); | |
//append a div to the #chart container div using a tooltip | |
var tip = d3.select("#chart").append("div") | |
.attr("class", "tooltip") | |
.style("opacity", 0); | |
//Select all circle elements, bind data and append to SVG element | |
var circles = svg.selectAll("circle") | |
.data(data) | |
.enter() | |
.append("circle"); | |
var circleAttributes = circles | |
.attr("cx", function(d){ | |
return xScale(d.Seconds); | |
}) | |
.attr("cy", function(d) { | |
return yScale(d.Place); | |
}) | |
.attr("r", function(d){ | |
if(d.Doping === ""){ | |
//no doping allegations get a slightly bigger circle | |
return 9; | |
} else { | |
return 6; | |
} | |
}) | |
.attr("class", "circles") | |
.attr("fill", function(d){ | |
if(d.Doping === ""){ | |
return color[0].code; | |
} else { | |
return color[1].code; | |
} | |
}) | |
.on("mouseover", function(d){ | |
tip.transition() | |
.duration(200) | |
.style("opacity", 0.9); | |
tip.html("<span><strong>" + d.Name + "</strong><br/><i>Place: </i>" + d.Place + "<br/><i>Time: </i>" + d.Time + "<br/><i>Year: </i>" + d.Year + "<br/><i>Nationality: </i>" + d.Nationality + "<br/><i>Doping: </i>" + d.Doping + "</span>") | |
//.style("left", (d3.event.pageX + 48) + "px") | |
//.style("top", (d3.event.pageY + 48 ) + "px"); | |
}) | |
.on("mouseout", function(d){ | |
tip.transition() | |
.duration(200) | |
.style("opacity", 0); | |
}); | |
//select all label elements, bind data and append to SVG element | |
var labels = svg.selectAll("labels") | |
.data(data) | |
.enter() | |
.append("text") | |
.text(function(d){ | |
return d.Name; | |
}) | |
.attr("x", function(d){ | |
return xScale(d.Seconds) + 10; | |
}) | |
.attr("y", function(d){ | |
return yScale(d.Place) + 4; | |
}) | |
.attr("class", "labels") | |
.attr("font-family", "roboto slab") | |
.attr("font-size", "12px") | |
.attr("fill", "#2c3e50") | |
.on("mouseover", function(d){ | |
tip.transition() | |
.duration(200) | |
.style("opacity", 0.9); | |
tip.html("<span><strong>" + d.Name + "</strong><br/><i>Place: </i>" + d.Place + "<br/><i>Time: </i>" + d.Time + "<br/><i>Year: </i>" + d.Year + "<br/><i>Nationality: </i>" + d.Nationality + "<br/><i>Doping: </i>" + d.Doping + "</span>") | |
}) | |
.on("mouseout", function(d){ | |
tip.transition() | |
.duration(200) | |
.style("opacity", 0); | |
}); | |
//Append X axis and move it to bottom (height) of SVG | |
svg.append("g") | |
.attr("class", "axis") | |
.attr("transform", "translate(0," + h + ")") | |
.call(xAxis); | |
//append Y axis | |
svg.append("g") | |
.attr("class", "axis") | |
.call(yAxis) | |
//Create a legend | |
var legend = svg.selectAll(".legend") | |
//create a g element for each element in color array | |
.data(color) | |
.enter() | |
.append("g") | |
.attr("class", "legend") | |
.attr("font-size", "14px") | |
.attr("font-style", "roboto slab") | |
.attr("transform", function(d,i){ | |
return ("translate(0," + i * 20 + ")"); | |
}) | |
legend.append("circle") | |
.attr("cx", w - 18) | |
.attr("cy", h/2) | |
.attr("r", 8) | |
.attr("width", 18) | |
.attr("height", 18) | |
.style("fill", function(d){ | |
return d.code; | |
}); | |
legend.append("text") | |
.attr("x", w - 28) | |
.attr("y", h/2 + 5) | |
.style("text-anchor", "end") | |
.text(function(d){ return d.text; }) | |
}); |
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
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link href="https://fonts.googleapis.com/css?family=Roboto+Slab" rel="stylesheet"> | |
<head> | |
<body> | |
<div class="container text-center"> | |
<h1>35 fastest times ever up Alpe d'Huez</h1> | |
</br> | |
<div id="chart"> | |
</div> | |
</div> | |
</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
body { | |
font-family: 'Roboto Slab', serif; | |
background-image: url("https://subtlepatterns.com/patterns/sos.png"); | |
} | |
svg { | |
background-color: white; | |
box-shadow: 0 0 10px #888888; | |
} | |
.axis path, | |
line { | |
fill: none; | |
stroke: black; | |
shape-rendering: crispEdges; | |
} | |
.axis text { | |
font-family: sans-serif; | |
font-size: 11px; | |
} | |
.tooltip { | |
position: absolute; | |
text-align: center; | |
top: 70px; | |
left: 160px; | |
vertical-align: middle; | |
width: 200px; | |
height: 180px; | |
padding: 5px; | |
font: 14px roboto slab; | |
background: #ecf0f1; | |
border: 0px; | |
border-radius: 8px; | |
} | |
.labels:hover { | |
fill: #e67e22; | |
} | |
.circles:hover { | |
stroke: black; | |
stroke-width: 2; | |
} | |
#chart { | |
position: relative; | |
} | |
.ylabel { | |
clear: both; | |
} | |
svg line { | |
stroke: lightgrey; | |
stroke-opacity: 0.3; | |
shape-rendering: crispEdges; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment