Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save rfprod/2ddd360628c57633455c to your computer and use it in GitHub Desktop.
Save rfprod/2ddd360628c57633455c to your computer and use it in GitHub Desktop.
Data Visualization with Scatterplot Chart

Data Visualization with Scatterplot Chart

Doping in Professional Bicycle Racing. User can see performance time visualized in a scatterplot graph. User can mouse over a plot to see a tooltip with additional details.

A Pen by V on CodePen.

License.

<div class="container-fluid nopadding">
<nav class="navbar navbar-inverse navbar-fixed-top topnav" role="navigation">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#toggle-nav" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand font-effect-neon" target=_blank href="http://codepen.io/rfprod"><span class="glyphicon glyphicon-wrench"></span> RFProd</a>
</div>
<div class="collapse navbar-collapse" id="toggle-nav">
<div class="container-fluid">
<ul class="nav navbar-nav navbar-right font-effect-emboss">
<li class="nav-tabs"><a href="#approot"><span class="glyphicon glyphicon-stats"></span> Data Visualization with Scatterplot Chart</a></li>
<li class="nav-tabs"><a href="https://gist.github.com/rfprod/2ddd360628c57633455c" target=_blank><span class="glyphicon glyphicon-download-alt" ></span> GIST</a></li>
</ul>
</div>
</div>
</nav>
<a name="approot"></a>
<div class="home sect">
<div class="container-fluid">
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12">
<h2 class="hidden-sm hidden-md hidden-xl"><span class="glyphicon glyphicon-stats"></span> Data Visualization with Scatterplot Chart</h2>
<div id="output">
Output
</div>
<span class="credits">info <a href="https://d3js.org/" target=_blank>D3.js</a> | <a href="https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json" target=_blank>data</a> <br/>licence <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target=_blank>GPL 3.0</a></span>
</div>
</div>
</div>
</div>
$(document).on('ready',function(){
(function (){
var UserInstructionsAndGDPChart = React.createClass({
render: function(){
return (
<span>
<p id="user-instructions">Doping in Professional Bicycle Racing visualization using D3.js.</p>
<div id="doping"></div>
</span>
);
}
});
ReactDOM.render(<UserInstructionsAndGDPChart />,document.getElementById('output'));
var chartContainerObj = d3.select('#doping');
$.getJSON('https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json', function(json){
var ranking = [], secondsDif = [], names = [];
for (var i=0;i<json.length;i++){
ranking.push(json[i].Place);
secondsDif.push(json[i].Seconds-json[0].Seconds);
names.push(json[i].Name);
}
console.log('ranking: '+ranking);
console.log('seconds difference vs fastest: '+secondsDif);
var k = 0, windowWidth = $(window).width();
if (windowWidth < 1000) k = windowWidth/500;
else k = windowWidth/500;
var width = $('#doping').width()-75*k, height = 400;
chartContainerObj.append('svg').attr('class','chart');
var circleRadius = width / secondsDif.length;
var chartObj = d3.select('.chart')
.attr("width", width)
.attr("height", height);
var y = d3.scale.linear().domain([0, d3.max(secondsDif, function(val) {return val;})]).range([height,10*k]);
var x = d3.scale.ordinal().domain(ranking).rangeRoundPoints([10, width]);
var div = d3.select("body").append("div").attr("class", "tooltip").style("opacity", 0);
var tooltip = d3.select('.tooltip');
var xCursorPosition = 0, yCursorPosition = 0;
var smallCircleRadius = circleRadius / 3;
var circle = chartObj.selectAll('g').data(ranking).enter()
.append('g')
.attr("transform", function(val, i) {return "translate(0,0)";});
circle.append("circle")
.attr("class", function(val,i){
return "circle-marker "+i;
})
.attr("cy",function(val,i){return y(secondsDif[i]);})
.attr("cx",function(val,i){return x(val);})
.attr("r", smallCircleRadius)
.on("mouseover", function(){
document.onmousemove = function(e){
xCursorPosition = e.pageX;
yCursorPosition = e.pageY;
}
d3.select(this).transition()
.duration(100)
.style("opacity", .3);
div.transition()
.duration(100)
.style("opacity", .9);
})
.on("mousemove", function(){
tooltip.style("left",xCursorPosition+"px");
tooltip.style("top",yCursorPosition-30+"px");
var index = d3.select(this).attr('class').substr(14,d3.select(this).attr('class').length-1);
var dataObj = json[index];
tooltip.html('Place: '+dataObj.Place+'<br>Time: '+dataObj.Time+'<br>Seconds: '+dataObj.Seconds+'<br>Name: '+dataObj.Name+'<br>Year: '+dataObj.Year+'<br>Nationality: '+dataObj.Nationality+'<br>Doping: '+dataObj.Doping);
})
.on("mouseout", function(){
document.onmousemove = null;
d3.select(this).transition()
.duration(400)
.style("opacity", 1);
div.transition()
.duration(400)
.style("opacity", 0);
});
var margin = {top: 10, right: 20, bottom: 30, left: 30};
chartObj
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + "0)");
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom");
chartObj.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.append("text")
.attr('class','axis-label')
.attr("text-anchor", "middle")
.attr("transform", "translate("+ (width/2) +","+margin.bottom+")")
.text("Position");
var yAxis = d3.svg.axis()
.scale(y)
.orient("right")
.ticks(10,'sec');
chartObj.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + width + ",0)")
.call(yAxis)
.append("text")
.attr('class','axis-label')
.attr("text-anchor", "middle")
.attr("transform", "translate("+ (margin.left+margin.right) +","+(height/2)+")rotate(-90)")
.text("Seconds behind the best time");
var circles = d3.select('.chart').selectAll('circle');
circles[0].forEach(function(element,index,array){
if (json[index].Doping == "") {
var cirObj = $('.'+index);
cirObj.attr('id','nodoping');
}
});
// legend markers
chartObj.append('g')
.attr('transform', function(val, i) {return "translate(0,0)";})
.append('circle')
.attr('id', 'nodoping')
.attr('cy', 10)
.attr('cx', 10)
.attr('r', smallCircleRadius);
chartObj.append('text')
.attr('class','legend-label')
.attr("text-anchor", "right")
.attr("transform", "translate("+ (10+smallCircleRadius) +","+(10+smallCircleRadius/1.5)+")")
.text("- no doping issues");
chartObj.append('g')
.attr('transform', function(val, i) {return "translate(0,0)";})
.append('circle')
.attr('id', 'doping')
.attr('cy', 30)
.attr('cx', 30)
.attr('r', smallCircleRadius);
chartObj.append('text')
.attr('class','legend-label')
.attr("text-anchor", "right")
.attr("transform", "translate("+ (30+smallCircleRadius) +","+(30+smallCircleRadius/1.5)+")")
.text("- doping issues present");
});
})();
});
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/react/0.14.7/react-dom.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://d3js.org/d3.v3.min.js"></script>
$black: #000000
$white: #ffffff
$grey: #bfbfbf
$blue: #3366cc
$green: #33cc33
body
color: $black
font-family: 'Play', sans-serif
font-size: 2.2em
overflow-x:hidden
.tooltip
position: absolute
text-align: center
width: auto !important
height: auto !important
padding: 2px
font: 12px sans-serif
background: lightsteelblue
border: 0px
border-radius: 8px
pointer-events: none
.nopadding
padding: 0
.navbar-brand
font-size: 1em
.home
min-height: 100vh
height: auto !important
.sect
padding-top: 8vh
.githublogo
height: 1em
h2
text-align: center
font-weight: bold
#output
text-align: center
width: 100%
height: auto !important
#user-instructions
text-align: center
font-size: 0.75em
margin-top: 1em
#doping
display: block
background-color: $grey
padding-top: 1em
padding-left: 1em
.chart
width: 97%
.legend-label
font: 12px sans-serif
.circle-marker
display: block
#nodoping
fill: $green
circle
fill: $blue
text
fill: $black
.axis
text
font: 9px sans-serif
path, line
fill: none
stroke: #000
shape-rendering: crispEdges
.axis-label
font: 15px sans-serif
.hidden
display: none
a
text-decoration: none
.credits
display: block
text-align: center
font-size: 0.75em
a:hover
text-decoration: none
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />
<link href="//cdnjs.cloudflare.com/ajax/libs/animate.css/3.2.3/animate.min.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css?family=Play&effect=neon" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment