Skip to content

Instantly share code, notes, and snippets.

@Kamalabot
Last active June 23, 2022 11:50
Show Gist options
  • Save Kamalabot/b6f9cc58e6826921994280c3568d48a7 to your computer and use it in GitHub Desktop.
Save Kamalabot/b6f9cc58e6826921994280c3568d48a7 to your computer and use it in GitHub Desktop.
FCC: D3 Scatter Plot
{
"scripts": [],
"styles": [],
"layout": "splitBottom"
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.4/d3.min.js" type="text/"></script>
</head>
<div class="main">
</div>
</html>
var projectName = 'scatter-Cyclist';
var url =
'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/cyclist-data.json';
//setting up the canvas and the scales
var margin = {
top: 100,
right: 20,
bottom: 30,
left: 60
},
width = 920 - margin.left - margin.right,
height = 630 - margin.top - margin.bottom;
var x = d3.scaleLinear().range([0, width]);
var y = d3.scaleTime().range([0, height]);
//schemeCategory20,20b,20c is stopped
var color = d3.scaleOrdinal(d3.schemeCategory10);
var timeFormat = d3.timeFormat('%M:%S');
var xAxis = d3.axisBottom(x).tickFormat(d3.format('d'));
var yAxis = d3.axisLeft(y).tickFormat(timeFormat);
// Define the div for the tooltip
var div = d3
.select('body')
.append('div')
.attr('class', 'tooltip')
.attr('id', 'tooltip')
.style('opacity', 0);
var svg = d3
.select('body')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.attr('class', 'chart')
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
d3.json(url)
.then((data) => {
data.forEach((d) => {
console.log(d.Place)
d.Place = +d.Place;
console.log(d)
var parsedTime = d.Time.split(':');
d.Time = new Date(1970, 0, 1, 0, parsedTime[0], parsedTime[1]);
});
x.domain([
d3.min(data, function (d) {
return d.Year - 1;
}),
d3.max(data, function (d) {
return d.Year + 1;
})
]);
y.domain(
d3.extent(data, function (d) {
return d.Time;
})
);
svg
.append('g')
.attr('class', 'x axis')
.attr('id', 'x-axis')
.attr('transform', 'translate(0,' + height + ')')
.call(xAxis)
.append('text')
.attr('class', 'x-axis-label')
.attr('x', width)
.attr('y', 6)
.style('text-anchor', 'end')
.text('Year');
svg
.append('g')
.attr('class', 'y axis')
.attr('id', 'y-axis')
.call(yAxis)
.append('text')
.attr('class', 'label')
.attr('transform', 'rotate(-90)')
.attr('y', 9)
.attr('dy', '.71em')
.style('text-anchor', 'end')
.text('Best Time (minutes)');
svg
.append('text')
.attr('transform', 'rotate(-90)')
.attr('x', -160)
.attr('y', -44)
.style('font-size', 18)
.text('Time in Minutes');
svg
.append('text')
.attr("x",400)
.attr("y",540)
.style('font-size',18)
.text("Year")
svg
.selectAll('.dot')
.data(data)
.enter()
.append('circle')
.attr('class', 'dot')
.attr('r', 8)
.attr('cx', (d) => {
return x(d.Year);
})
.attr('cy', (d) => {
return y(d.Time);
})
//they are just attributes
.attr('data-xvalue', (d) => {
return d.Year;
})
.attr('data-yvalue', (d) => {
return d.Time.toISOString();
})
.style('fill', function (d) {
return color(d.Doping !== '');
})
.on('mouseover', function (event, d) {
div.style('opacity', 0.9);
div.attr('data-year', d.Year);
div
.html(
d.Name +
': ' +
d.Nationality +
'<br/>' +
'Year: ' +
d.Year +
', Time: ' +
timeFormat(d.Time) +
(d.Doping ? '<br/><br/>' + d.Doping : '')
)
.style('left', event.pageX + 'px')
.style('top', event.pageY - 28 + 'px');
})
.on('mouseout', function () {
div.style('opacity', 0);
});
// title
svg
.append('text')
.attr('id', 'title')
.attr('x', width / 2)
.attr('y', 0 - margin.top / 2)
.attr('text-anchor', 'middle')
.style('font-size', '30px')
.text('Doping in Professional Bicycle Racing');
// subtitle
svg
.append('text')
.attr('x', width / 2)
.attr('y', 0 - margin.top / 2 + 25)
.attr('text-anchor', 'middle')
.style('font-size', '20px')
.text("35 Fastest times up Alpe d'Huez");
var legendContainer = svg.append('g').attr('id', 'legend');
var legend = legendContainer
.selectAll('#legend')
.data(color.domain())
.enter()
.append('g')
.attr('class', 'legend-label')
.attr('transform', function (d, i) {
return 'translate(0,' + (height / 2 - i * 20) + ')';
});
legend
.append('rect')
.attr('x', width - 18)
.attr('width', 18)
.attr('height', 18)
.style('fill', color);
legend
.append('text')
.attr('x', width - 24)
.attr('y', 9)
.attr('dy', '.35em')
.style('text-anchor', 'end')
.text(function (d) {
if (d) {
return 'Riders with doping allegations';
} else {
return 'No doping allegations';
}
});
})
.catch((err) => console.log(err));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.4/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.min.js"></script>
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
.chart {
display: block;
margin: auto;
background-color: cornsilk;
}
body {
font: 10px sans-serif;
width: 100%;
height: 100%;
}
.main {
position: relative;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.dot {
stroke: #000;
opacity: 0.8;
}
div.tooltip {
position: absolute;
padding: 10px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment