Last active
July 16, 2017 15:20
-
-
Save greaneym/9e143318d54563be664c923a036faee9 to your computer and use it in GitHub Desktop.
fcc zipline using d3 for scatter plot
This file contains 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
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<title>FCC Zipline Scatter Plot using D3</title> | |
<style> | |
#header1 { | |
background: url("https://static.pexels.com/photos/248547/pexels-photo-248547.jpeg"); | |
width:100%; | |
height: 90%; | |
background-size: cover; | |
z-index: -10; | |
} | |
html { | |
width:100%; | |
height: 100%; | |
font-color: white; | |
} | |
/* | |
.bg-img { | |
background: url('bikes.jpeg') center center no-repeat ; | |
width: 100%; | |
height: 100%; | |
background-size: cover; */ | |
/* &:before { | |
content: ''; | |
position: absolute; | |
top: 0; | |
right: 0; | |
bottom: 0; | |
left: 0; | |
background-image: linear-gradient(to bottom right,#002f4b,#dc4225); | |
opacity: .6; | |
} */ | |
} | |
body{ | |
background-color: transparent; | |
font-color: white; | |
} | |
.container { | |
background-color: transparent; | |
position: absolute; | |
/* left:-200px%; | |
top:-500px; | |
left:200px; | |
top:500px; */ | |
height:100%; | |
width:100%; | |
/ *border-style:solid; | |
border-width:2px; | |
border-color:green; | |
*/ | |
} | |
.ttcontainer { | |
position: absolute; | |
left:300px; | |
top:500px; | |
stroke: #fff; | |
font-color: white; | |
border-style:solid; | |
border-width:2px; | |
border-color:black; | |
background-color: white; | |
z-axis: 200; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
//fill: white; | |
stroke: #fff; | |
shape-rendering: crispEdges; | |
background-color: white; | |
} | |
.axistext { | |
font-family: sans-serif; | |
font-size: 10px; | |
stroke: #fff; | |
/* text-shadow: 2px 2px black; */ | |
z-index:200; | |
} | |
g.axis, g.tick.text { | |
stroke: #fff; | |
} | |
div.tooltip { | |
position: absolute; | |
text-align: center; | |
left:250px; | |
width: 200px; | |
height: 70px; | |
padding: 2px; | |
font: 14px sans-serif; | |
font-style: bold; | |
background-color: white; | |
stroke: #fff; | |
border: 3px; | |
border-radius: 8px; | |
border-color: #3182bd; | |
z-index: 200; | |
} | |
.hidden { | |
display: none; | |
} | |
.legendtext { | |
font-family: sans-serif; | |
/* font-color: black; */ | |
font-color: white; | |
font-size: 10px; | |
z-index:200; | |
} | |
.legendrect { | |
stroke-width: 2; | |
} | |
h1 { | |
color: white; | |
/* background-color: rgba(0, 0, 0, 0.7); */ | |
background-color: rgba(0, 0, 0, 0.75); | |
/*padding-top: 0px; | |
padding-bottom: 0px; | |
padding-left: 0px; | |
padding-right: 0px; */ | |
width: 100%; | |
height: 100%; | |
background-size: cover; | |
} | |
</style> | |
<body> | |
<!-- <script src="/d3new/d3.js"></script>--> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script> | |
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script> --> | |
<!-- <script src="/camp/clock/dtest/d3.v4.js"></script> --> | |
<script> | |
//As a starting point used book “Interactive Data Visualization for the Web” by Scott Murray, published in March 2013 by O’Reilly. | |
//24_scatterplot_labels.html from chapter 6 | |
// challenges for me since being away from d3.js for a while were, | |
// finding out the name replacements for functions in d3 v3 and d3 v5 | |
// placing a background url that would not compete with text labels on graph | |
// placing text labels inside the margins that would not get clipped | |
// other challenge, background display with cover | |
//tooltips used from barchart on previous fcc zipline | |
//legend help from | |
//http://zeroviscosity.com/d3-js-step-by-step/step-3-adding-a-legend | |
//Width and height | |
var w = 550; | |
var h = 340; | |
var padding = 30; | |
var parseDate = d3.timeFormat("%Y-%m-%d %H:%M:%S").parse; | |
var now = new Date; | |
// Formatters for counts and times (converting numbers to Dates). | |
var formatCount = d3.format(",.0f"), | |
formatTime = d3.timeFormat("%H:%M"), | |
formatMinutes = function(d) { return formatTime(new Date(2012, 0, 1, 0, d)); }; | |
var parseDate = d3.timeFormat("%Y-%m-%d %H:%M:%S"); | |
var jdata = {}; | |
var diff, fastTime,lastTime; | |
//d3.json("cyclist.json", function(error,data) { | |
d3.json("https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json", function(error,data) { | |
jdata = data; | |
jdata.forEach(function (d,i) { | |
//console.log('d,i',d,i); | |
d.raceTime = d.Time; | |
d.creat_time = parseDate(d.Time); | |
d.place = +d.Place; | |
d.secs = +d.Seconds; | |
if (i === 0) { fastTime = d.secs; } | |
d.name = d.Name; | |
d.year = d.Year; | |
//d.diff = fastTime - d.secs; | |
d.diff = d.secs - fastTime; | |
//console.log("d.diff",d.diff); | |
if (d.Doping === '') { d.class = "violation"; } | |
else { d.class = "no_violation"; } | |
if (i === 34) { lastTime = d.secs + 500;console.log("lastTime",lastTime); } | |
//console.log('jdata',jdata); | |
}); | |
//Create scale functions | |
//var xScale = d3.scale.linear() //older version d3 use this | |
var xScale = d3.scaleTime() | |
.domain([d3.max(jdata, function(d) { return d.diff + 5; }),-3]) | |
.range([padding, w - padding]); | |
//`var yScale = d3.scale.linear() | |
var yScale = d3.scaleLinear() | |
.domain([d3.max(jdata, function(d) { return d.place + 1; }),0]) | |
.range([h - padding, padding]); | |
//var rScale = d3.scale.linear() | |
var rScale = d3.scaleLinear() | |
.domain([0, d3.max(jdata, function(d) { | |
//console.log("d3maxjdata", d3.max(jdata, function(d) { d.place;)}); | |
//console.log("d3maxjdata",d.place); | |
return d.place; })]) | |
.range([0, 35]); | |
//var x = d3.scale.linear() | |
var x = d3.scaleTime() | |
.range([0, w + 50]) | |
.domain([5000,0]); | |
//var y = d3.scale.ordinal() | |
var y = d3.scaleLinear() | |
//.rangeRoundPoints([h-10,0]) | |
//.rangeRoundPoints([35,0]) | |
.range([35,0]) | |
.domain(data.map(function(d){ | |
//console.log("d.place in y domain",d.place); | |
return d.place;})); | |
//Define X axis | |
// var xAxis = d3.svg.axis() | |
var xAxis = d3.axisBottom() | |
.scale(xScale) | |
.ticks(6) | |
.tickFormat(formatMinutes); | |
//Define Y axis | |
//var yAxis = d3.svg.axis() | |
var yAxis = d3.axisLeft() | |
.scale(yScale) | |
.ticks(7); | |
//Create SVG element | |
var svg = d3.select("#container") | |
.append("svg") | |
.attr("width", w) | |
.attr("height", h); | |
var g = svg.append('g').attr('transform', 'translate(0,0)'); // use g for several appends | |
var div = d3.select("#container").append("div") | |
.attr("class", "tooltip") | |
.attr("fill", "white") | |
.style("opacity", 0); | |
//Create circles | |
svg.selectAll("circle") | |
.data(jdata) | |
.enter() | |
.append("circle") | |
.style("fill", function (d) { | |
if (d.class === "violation") { | |
return "green"; } | |
else if (d.class ==="no_violation") { | |
return "red"; }; | |
}) | |
.attr("cx", function(d) { | |
return xScale((d.diff)); | |
}) | |
.attr("cy", function(d) { | |
return yScale(d.place); | |
}) | |
.attr("r", function(d) { | |
//console.log("r",Math.sqrt(h - d.place)); | |
return 2; | |
})//; | |
.attr("transform", "translate(12," + 5 + ")") | |
.on("mouseover", function(d,i) { | |
div.transition(300) | |
.style("opacity", 1.0); | |
div .html(d.name + "<br>" + "Year: " + d.year + " Time: " + d.raceTime + "<br/>"+ d.Doping) | |
//.style("left", (d3.event.pageX) + "px") | |
//.style("top", (d3.event.pageY - 28) + "px") | |
.style("left", "352px") | |
.style("top", "202px") | |
.style("z-index", "200") | |
.style("font-color", "white") | |
.style("fill", "white") | |
.style("stroke", "white"); | |
}); | |
div.on("mouseout", function(d) { | |
div.transition() | |
.duration(20) | |
.style("opacity", 0); | |
}); | |
//Create labels | |
svg.selectAll("text") | |
.data(jdata) | |
.enter() | |
.append("text") | |
.text(function(d) { | |
return d.name; | |
}) | |
.attr("x", function(d) { | |
//return xScale(format(d.Time)); | |
return xScale((d.diff)); | |
//return d.diff; | |
}) | |
.attr("y", function(d) { | |
return yScale(d.place); | |
}) | |
.attr("font-family", "sans-serif") | |
.attr("font-size", "8px") | |
.attr("fill", "red") | |
.attr("transform", "translate(14," + 7 + ")"); | |
//Create X axis | |
svg.append("g") | |
.attr("class", "axis") | |
//.attr("class", "axistext") | |
.attr("transform", "translate(0," + (h - padding) + ")") | |
.call(xAxis); | |
//Create Y axis | |
svg.append("g") | |
.attr("class", "axis") | |
.attr("transform", "translate(" + padding + ",0)") | |
.call(yAxis); | |
//append titles and axis legends | |
var title = d3.selectAll("svg").append("g:text") | |
.attr('text-anchor', 'end') | |
.attr("x", 450) | |
.attr("y", 40) | |
.attr("class", "axistext") | |
.text("Doping in Professional Bike Racing"); | |
var legend = d3.selectAll("svg").append("g:text") | |
.attr('text-anchor', 'end') | |
.attr("x", 350) | |
.attr("y", 338) | |
.attr("class", "axistext") | |
.attr("fill", "white") | |
.attr("z-index", "200") | |
.text("Minutes Behind Fastest Time") | |
.attr("fill", "white") | |
.attr("z-index", "200"); | |
g.append('g') | |
.append('text') | |
.attr('transform', 'rotate(-90)') | |
.attr('y', 2) //acts as x because rotated | |
.attr('x', -125)// acts as y because rotated | |
.attr('dy', '0.6em') //spacing from axis | |
.attr('text-anchor', 'end') | |
.attr("class", "axistext") | |
.text("Ranking"); | |
var legendRectSize = 10; | |
var legendSpacing = 4; | |
var colorRules = d3.scaleOrdinal() | |
.domain(["violation", "no_violation"]) | |
.range(["red", "green"]); | |
//color is not working so am using fill | |
var legendrect = svg.selectAll('svg') | |
.data(colorRules) | |
.enter() | |
.append('g') | |
.attr('class', 'legend') | |
.attr('transform', function(d, i) { | |
var height = legendRectSize + legendSpacing; | |
//console.log("legend height",height); | |
//var offset = height * color.domain().length / 2; | |
var offset = height * 2; | |
var horz = -2 * legendRectSize; | |
var vert = i * height - offset; | |
return 'translate(' + horz + ',' + vert + ')'; | |
}); | |
svg.append('rect') | |
.attr('x', 375) | |
.attr('y', 280) | |
.attr('width', legendRectSize) | |
.attr('height', legendRectSize) | |
.style('fill', "red") | |
.style('stroke', 'white'); | |
svg.append('text') | |
.attr('x', 390) | |
.attr('y', 288) | |
.attr("class", "legendtext") | |
.style('stroke', 'white') | |
.style('fill', 'white') | |
.text(function(d) { return "Doping Allegations Found"; }); | |
svg.append('rect') | |
.attr('x', 375) | |
.attr('y', 290) | |
.attr('width', legendRectSize) | |
.attr('height', legendRectSize) | |
.style('fill', "green") | |
.style('stroke', 'white'); | |
svg.append('text') | |
.attr('x', 390) | |
.attr('y', 300) | |
.attr("class", "legendtext") | |
.style('stroke', 'white') | |
.style('fill', 'white') | |
.text(function(d) { return "No Doping Allegations Found"; }); | |
}); | |
</script> | |
</body> | |
<div id="container" class="bg-img" alt="bike racing picture"> | |
<div class="header"> | |
<div class="overlay"> | |
<div class="container" id="header1"> | |
<h1></h1> | |
</div> | |
</div> | |
</div> | |
<div id="ttcontainer"> | |
<div id="tooltip" class="hidden"> </div> | |
</html> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment