Skip to content

Instantly share code, notes, and snippets.

@Cynnexis
Last active November 14, 2019 22:25
Show Gist options
  • Select an option

  • Save Cynnexis/a11afbe4507e300bbdee4d595b0587bf to your computer and use it in GitHub Desktop.

Select an option

Save Cynnexis/a11afbe4507e300bbdee4d595b0587bf to your computer and use it in GitHub Desktop.
TP2-Intro-D3-BACCUET-Anthony-BERGER-Valentin
license: mit
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Raleway:300,400,700&display=swap" rel="stylesheet">
<style lang="css">
.mini text {
font: 9px sans-serif;
}
div.tooltip {
position: absolute;
text-align: center;
width: 100px;
height: 50px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0;
border-radius: 8px;
pointer-events: none;
}
.navbar + .container {
margin-top: 100px;
}
.row > h1 {
margin-bottom: 30px;
}
</style>
<title>Introduction to D3</title>
</head>
<body>
<div class="navbar navbar-expand-lg fixed-top navbar-dark bg-primary">
<div class="container">
<h1 class="navbar-brand">TP2 - Introduction to D3</h1>
</div>
</div>
<div class="container">
<div class="row">
<h1 class="col-12">Création d'une timeline</h1>
<div id="student-placeholder" class="col-12"></div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-selection-multi.v1.min.js"></script>
<script type="text/javascript">
/**
* Lighten or darken the given color.
* Source code inspired from https://stackoverflow.com/a/57401891/7347145.
* @param color The color to change.
* @param amount The amount to change (positive = lighten, negative = darken).
* @returns {string} The new color.
*/
function adjust(color, amount) {
return '#' + color.replace(/^#/, '').replace(/../g, color => ('0'+Math.min(255, Math.max(0, parseInt(color, 16) + amount)).toString(16)).substr(-2));
}
$(document).ready(function() {
//data
let prenoms = ["Etudiant 1", "Etudiant 2", "Etudiant 3"];
let nbEtudiants = prenoms.length;
let prenomsColor = ["#F79174", "#839868", "#97A6B2"];
let weekdays = ["lundi", "mardi", "mercredi", "jeudi", "vendredi"];
let items = [
{ id: 0, jour: weekdays[0], start: 0, end: 70 },
{ id: 0, jour: weekdays[1], start: 230, end: 350 },
{ id: 0, jour: weekdays[2], start: 485, end: 600 },
{ id: 0, jour: weekdays[3], start: 670, end: 800 },
{ id: 0, jour: weekdays[4], start: 880, end: 1000 },
{ id: 1, jour: weekdays[0], start: 0, end: 120 },
{ id: 1, jour: weekdays[1], start: 250, end: 400 },
{ id: 1, jour: weekdays[2], start: 500, end: 600 },
{ id: 1, jour: weekdays[3], start: 700, end: 850 },
{ id: 1, jour: weekdays[4], start: 1000, end: 1110 },
{ id: 2, jour: weekdays[0], start: 0, end: 60 },
{ id: 2, jour: weekdays[1], start: 230, end: 400 },
{ id: 2, jour: weekdays[2], start: 440, end: 600 },
{ id: 2, jour: weekdays[3], start: 690, end: 800 },
{ id: 2, jour: weekdays[4], start: 920, end: 1200 },
];
let timeBegin = 0;
let timeEnd = 1200; //5 jours * 24h * 10
let w = 960;
let h = 100;
let height = nbEtudiants * 12 + 50;
let defaultFonts = "'Raleway', monospace, sans-serif";
let defaultTransition = "easeQuad";
let defaultTransitionDuration = 200;
// Define the div for the tooltip
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
// TODO scales
// chart
let chart = d3
.select("#student-placeholder")
.append("svg")
.attr("width", w)
.attr("height", h)
.attr("class", "chart");
// Create a scale for the y-axis, based on 'prenoms' array
let yScalePrenoms = d3.scaleLinear().range([0, height]).domain([0, prenoms.length]);
let xScaleWeekdays = d3.scaleLinear().range([150, w]).domain([0, weekdays.length]);
let xScaleItem = d3.scaleLinear().range([150, w]).domain([timeBegin, timeEnd - timeBegin]);
// Draw 1 lane per student
let g = chart.append('g');
g.selectAll("text")
.data(prenoms)
.enter()
.append("text")
.text(prenom => prenom)
.attrs({
x: 100,
y: (prenom, index) => yScalePrenoms(index) + 10,
"font-size": 12,
"text-anchor": "middle",
"font-family": defaultFonts,
});
// draw rectangles per item
g = chart.append('g');
g.selectAll("rect")
.data(items)
.enter()
.append("rect")
.attrs({
x: item => xScaleItem(item["start"]),
y: item => yScalePrenoms(item["id"]),
width: item => xScaleItem(item["end"]) - xScaleItem(item["start"]),
height: 15,
fill: item => prenomsColor[item["id"]],
})
// color change on hovering rectangles
.on("mouseover", function(item) {
d3.select(this)
.transition(defaultTransition)
.duration(defaultTransitionDuration)
.attr("fill", adjust(prenomsColor[item["id"]], 20));
tooltip
.transition(defaultTransition)
.duration(defaultTransitionDuration)
.style("opacity", .9);
tooltip.html(prenoms[item["id"]] + " slept from " + item["start"] + " to " + item["end"] + " on " + item["jour"])
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + "px")
})
.on("mouseout", function(item) {
d3.select(this)
.transition(defaultTransition)
.duration(defaultTransitionDuration)
.attr("fill", prenomsColor[item["id"]]);
tooltip
.transition(defaultTransition)
.duration(defaultTransitionDuration)
.style("opacity", 0);
});
// draw 1 line per day
g = chart.append('g');
g.selectAll("line")
.data(weekdays)
.enter()
.append("line")
.attrs({
x1: (weekday, index) => xScaleWeekdays(index),
y1: 0,
x2: (weekday, index) => xScaleWeekdays(index),
y2: h - 15,
"stroke": "gray",
"stroke-width": 1,
});
g.selectAll("text")
.data(weekdays)
.enter()
.append("text")
.text(weekday => weekday)
.attrs({
x: (weekday, index) => xScaleWeekdays(index),
y: h - 5,
})
.style("font-size", 12)
.style("text-anchor", "middle")
.style("font-family", defaultFonts);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment