Skip to content

Instantly share code, notes, and snippets.

@chemok78
Created January 25, 2017 03:44
Show Gist options
  • Save chemok78/8d0e4894c426a4208e41a255967bb8c3 to your computer and use it in GitHub Desktop.
Save chemok78/8d0e4894c426a4208e41a255967bb8c3 to your computer and use it in GitHub Desktop.
D3 JS Scatterplot Graph Fastest Times Ever Up Alpe d'Huez
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; })
});
<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>
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