Newer
Older
d3.json("sleep_combined_clean.json").then(function(data) {
// Fonction pour filtrer les mois en fonction de l'année sélectionnée
function getMonthsForYear(year) {
return d3.timeMonths(new Date(year + "-01-01"), new Date(year + "-12-31"));
}
// Parsing des dates et tri des données par mois
data.forEach(d => {
d.date = d3.timeParse("%Y-%m-%d")(d.date);
});
// Création du groupe pour chaque membre
var members = ["Anis", "Maya", "Corentin", "Amira"];
// Fonction de mise à jour du graphique en fonction de l'année et des membres sélectionnés
function updateChart(selectedYear, selectedMembers) {
const monthsForYear = getMonthsForYear(selectedYear);
// Filtrage des données par mois
var groupedData = d3.group(data, d => d.month);
// Transformation des données en format plus approprié pour la visualisation
var nestedData = monthsForYear.map(month => {
const valuesForMonth = groupedData.get(month) || [];
const avgMonthSleep = selectedMembers.map(member => {
const memberData = valuesForMonth.filter(d => d[member] !== null);
return {
member: member,
value: memberData.length > 0 ? d3.mean(memberData, v => v[member]) : null // Utiliser null pour les données manquantes
return {
month: month,
};
});
// Dimensions du graphique
var width = 800, height = 400;
var margin = { top: 20, right: 120, bottom: 60, left: 60 };
.range([margin.left, width - margin.right])
.padding(0.05); // Réduire l'espacement entre les mois
var y = d3.scaleLinear()
.domain([0, d3.max(nestedData, d => d3.max(d.values, v => v.value))])
.nice()
.range([height - margin.bottom, margin.top]);
var color = d3.scaleOrdinal()
.range(["#ff6347", "#4682b4", "#32cd32", "#ff1493"]);
var svg = d3.select("#chart")
.attr("width", width)
.attr("height", height);
// Nettoyer le SVG avant de redessiner
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x)
.tickFormat(d3.timeFormat("%B")) // Utilisation du format du mois pour l'axe X
.ticks(d3.timeMonth.every(1)) // Affichage de chaque mois
)
.selectAll("text")
.style("text-anchor", "middle")
.attr("transform", `translate(${margin.left}, 0)`)
// Ajouter les titres des axes
svg.append("text")
.attr("x", width / 2)
.attr("y", height - 5)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Mois");
svg.append("text")
.attr("transform", "rotate(-90)")
.attr("x", -height / 2)
.attr("y", 20)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Heures de sommeil");
// Création du tooltip
var tooltip = d3.select("body").append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background-color", "rgba(0, 0, 0, 0.7)")
.style("color", "white")
.style("padding", "5px")
.style("border-radius", "5px")
.style("pointer-events", "none");
svg.append("g")
.selectAll("g")
.data(nestedData)
.enter().append("g")
.attr("transform", d => `translate(${x(d.month)}, 0)`)
.data(d => d.values.filter(v => selectedMembers.includes(v.member) && v.value !== null)) // Filtrer les données null
.attr("x", (d, i) => i * (x.bandwidth() / selectedMembers.length)) // Coller les barres
.attr("y", d => y(d.value))
.attr("width", x.bandwidth() / selectedMembers.length - 1) // Ajuster la largeur des barres
.attr("height", d => height - margin.bottom - y(d.value))
.attr("fill", d => color(d.member))
.on("mouseover", function(event, d) {
tooltip.style("visibility", "visible")
.text(d.member + ": " + d.value.toFixed(2) + " heures");
})
.on("mousemove", function(event) {
tooltip.style("top", (event.pageY + 5) + "px")
.style("left", (event.pageX + 5) + "px");
})
.on("mouseout", function() {
tooltip.style("visibility", "hidden");
});
// Ajouter la légende
var legend = svg.append("g")
.attr("transform", `translate(${width - margin.right + 20}, ${margin.top})`);
selectedMembers.forEach((member, i) => {
var legendRow = legend.append("g")
.attr("transform", `translate(0, ${i * 20})`);
legendRow.append("rect")
.attr("width", 15)
.attr("height", 15)
.attr("fill", color(member));
legendRow.append("text")
.attr("x", 20)
.attr("y", 12)
.style("font-size", "12px")
.text(member);
});
// Initialisation avec tous les membres
updateChart(2024, ["Anis", "Maya", "Corentin", "Amira"]);
// Gestion des changements dans les sélections
d3.select("#yearSelect").on("change", function() {
const selectedYear = this.value;
const selectedMembers = Array.from(document.querySelectorAll("#memberSelect input:checked")).map(input => input.value);
updateChart(selectedYear, selectedMembers);
});
d3.select("#memberSelect").on("change", function() {
const selectedYear = d3.select("#yearSelect").node().value;
const selectedMembers = Array.from(document.querySelectorAll("#memberSelect input:checked")).map(input => input.value);
updateChart(selectedYear, selectedMembers);